aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntti Määttä <antti.maatta@qt.io>2019-10-11 12:10:54 +0300
committerAntti Määttä <antti.maatta@qt.io>2019-10-18 11:08:03 +0300
commitda27e66f578e845eab3f73e1cd023a8dbb12ac27 (patch)
tree43d425bff50aafc83957e60e6b1303fdb6c07bbb
parentb6115ead6793e3943a111ab2729cdabb737a35e9 (diff)
Add support for antialiasingv5.14.0-beta2
- Allow ideal format functions to select multisample format to support MSAA in direct render modes - Add multisample and supersample AA modes for Texture render mode Task-number: QTBUG-76692 Change-Id: Iddcac437391656c3c933b42c4d23cfc6b1758022 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
-rw-r--r--examples/quick3d/simple/main.cpp2
-rw-r--r--examples/quick3d/simple/main.qml14
-rw-r--r--src/quick3d/qquick3dscenerenderer.cpp81
-rw-r--r--src/quick3d/qquick3dscenerenderer_p.h8
-rw-r--r--src/quick3d/qquick3dviewport.cpp59
-rw-r--r--src/quick3d/qquick3dviewport_p.h2
-rw-r--r--src/render/qssgrendertexturebase_p.h1
-rw-r--r--src/runtimerender/rendererimpl/qssgrendererimpllayerrenderdata.cpp4
-rw-r--r--tests/manual/runtimerender/testbed/renderwindow.cpp2
9 files changed, 151 insertions, 22 deletions
diff --git a/examples/quick3d/simple/main.cpp b/examples/quick3d/simple/main.cpp
index 8e886b61..5743c575 100644
--- a/examples/quick3d/simple/main.cpp
+++ b/examples/quick3d/simple/main.cpp
@@ -60,7 +60,7 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv);
- QSurfaceFormat::setDefaultFormat(QQuick3DViewport::idealSurfaceFormat());
+ QSurfaceFormat::setDefaultFormat(QQuick3DViewport::idealSurfaceFormat(4));
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
diff --git a/examples/quick3d/simple/main.qml b/examples/quick3d/simple/main.qml
index 59784d15..130d90a8 100644
--- a/examples/quick3d/simple/main.qml
+++ b/examples/quick3d/simple/main.qml
@@ -59,10 +59,21 @@ Window {
height: 720
visible: true
+ MouseArea {
+ anchors.fill: parent
+ property bool msenab: true
+ onClicked: {
+ environ.multisampleAAMode = msenab ? SceneEnvironment.NoAA : SceneEnvironment.X4
+ msenab = !msenab
+ console.log("aa enabled: " + msenab)
+ }
+ }
+
View3D {
id: layer1
anchors.fill: parent
camera: camera
+ renderMode: View3D.Texture
// Light always points the same direction as camera
// Light {
@@ -76,12 +87,14 @@ Window {
// }
environment: SceneEnvironment {
+ id: environ
probeBrightness: 1000
clearColor: "green"
backgroundMode: SceneEnvironment.Color
lightProbe: Texture {
source: "maps/OpenfootageNET_garage-1024.hdr"
}
+ multisampleAAMode: SceneEnvironment.X4
}
Node {
@@ -193,6 +206,7 @@ Window {
}
Model {
+ visible: layer1.renderMode == View3D.Texture
position: Qt.vector3d(-300, 0, 0)
source: "#Cube"
materials: [ FrostedGlassMaterial {
diff --git a/src/quick3d/qquick3dscenerenderer.cpp b/src/quick3d/qquick3dscenerenderer.cpp
index 306dff77..c4955179 100644
--- a/src/quick3d/qquick3dscenerenderer.cpp
+++ b/src/quick3d/qquick3dscenerenderer.cpp
@@ -41,6 +41,7 @@
#include <QtQuick3DRender/private/qssgrenderframebuffer_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrenderlayer_p.h>
+#include <QtQuick3DRuntimeRender/private/qssgrendererutil_p.h>
#include <QtQuick/QQuickWindow>
QT_BEGIN_NAMESPACE
@@ -141,6 +142,9 @@ void SGFramebufferObjectNode::handleScreenChange()
QQuick3DSceneRenderer::QQuick3DSceneRenderer(QWindow *window)
: m_window(window)
+ , m_multisampleFbo(nullptr)
+ , m_supersampleFbo(nullptr)
+ , m_fbo(nullptr)
{
QOpenGLContext *openGLContext = QOpenGLContext::currentContext();
@@ -167,6 +171,8 @@ QQuick3DSceneRenderer::~QQuick3DSceneRenderer()
{
delete m_layer;
delete m_fbo;
+ delete m_multisampleFbo;
+ delete m_supersampleFbo;
}
GLuint QQuick3DSceneRenderer::render()
@@ -174,16 +180,45 @@ GLuint QQuick3DSceneRenderer::render()
if (!m_layer)
return 0;
+ const bool ssaaEnabled = this->m_layer->multisampleAAMode == QSSGRenderLayer::AAMode::SSAA;
+ const bool msaaEnabled = this->m_layer->multisampleAAMode > QSSGRenderLayer::AAMode::SSAA;
+
m_sgContext->beginFrame();
- m_renderContext->setRenderTarget(m_fbo->fbo);
- m_sgContext->renderList()->setViewport(QRect(0, 0, m_surfaceSize.width(), m_surfaceSize.height()));
+
+ // select correct fbo for aa
+ auto fbo = m_multisampleFbo ? m_multisampleFbo : m_fbo;
+ fbo = m_supersampleFbo ? m_supersampleFbo : fbo;
+ fbo = ssaaEnabled || msaaEnabled ? fbo : m_fbo;
+
+ m_renderContext->setRenderTarget(fbo->fbo);
+ QSize surfaceSize = m_surfaceSize;
+ if (ssaaEnabled && m_supersampleFbo)
+ surfaceSize *= SSAA_Multiplier;
+ m_sgContext->renderList()->setViewport(QRect(0, 0, surfaceSize.width(), surfaceSize.height()));
m_sgContext->setWindowDimensions(m_surfaceSize);
- m_sgContext->renderer()->prepareLayerForRender(*m_layer, m_surfaceSize, false, nullptr, true);
+ m_sgContext->renderer()->prepareLayerForRender(*m_layer, surfaceSize, false, nullptr, true);
m_sgContext->runRenderTasks();
- m_sgContext->renderer()->renderLayer(*m_layer, m_surfaceSize, true, QVector3D(0, 0, 0), false);
+ m_sgContext->renderer()->renderLayer(*m_layer, surfaceSize, true, QVector3D(0, 0, 0), false);
m_sgContext->endFrame();
+ if ((msaaEnabled && m_multisampleFbo) || (ssaaEnabled && m_supersampleFbo)) {
+ m_renderContext->setRenderTarget(m_fbo->fbo);
+ m_renderContext->setReadTarget(m_supersampleFbo ? m_supersampleFbo->fbo
+ : m_multisampleFbo->fbo);
+ if (m_supersampleFbo) {
+ m_renderContext->blitFramebuffer(0, 0, surfaceSize.width(), surfaceSize.height(),
+ 0, 0, m_surfaceSize.width(), m_surfaceSize.height(),
+ QSSGRenderClearValues::Color,
+ QSSGRenderTextureMagnifyingOp::Linear);
+ } else {
+ m_renderContext->blitFramebuffer(0, 0, m_surfaceSize.width(), m_surfaceSize.height(),
+ 0, 0, m_surfaceSize.width(), m_surfaceSize.height(),
+ QSSGRenderClearValues::Color,
+ QSSGRenderTextureMagnifyingOp::Nearest);
+ }
+ }
+
if (dumpPerfTiming) {
if (++frameCount == 60) {
m_sgContext->performanceTimer()->dump();
@@ -285,6 +320,27 @@ void QQuick3DSceneRenderer::synchronize(QQuick3DViewport *item, const QSize &siz
if (m_fbo)
delete m_fbo;
+ auto msaaModeSamples = [](QSSGRenderLayer::AAMode mode) -> int {
+ switch (mode) {
+ case QSSGRenderLayer::AAMode::X2:
+ return 2;
+ case QSSGRenderLayer::AAMode::X4:
+ case QSSGRenderLayer::AAMode::X8:
+ return 4;
+ case QSSGRenderLayer::AAMode::NoAA:
+ default:
+ break;
+ }
+ return 1;
+ };
+ if (msaaModeSamples(m_layer->multisampleAAMode) > 1) {
+ m_multisampleFbo
+ = new FramebufferObject(m_surfaceSize, m_renderContext,
+ msaaModeSamples(m_layer->multisampleAAMode));
+ } else if (m_layer->multisampleAAMode == QSSGRenderLayer::AAMode::SSAA) {
+ m_supersampleFbo = new FramebufferObject(m_surfaceSize * SSAA_Multiplier,
+ m_renderContext);
+ }
m_fbo = new FramebufferObject(m_surfaceSize, m_renderContext);
m_layerSizeIsDirty = false;
}
@@ -403,18 +459,25 @@ void QQuick3DSceneRenderer::addNodeToLayer(QSSGRenderNode *node)
m_layer->addChild(*node);
}
-QQuick3DSceneRenderer::FramebufferObject::FramebufferObject(const QSize &s, const QSSGRef<QSSGRenderContext> &context)
+QQuick3DSceneRenderer::FramebufferObject::FramebufferObject(const QSize &s, const QSSGRef<QSSGRenderContext> &context, int msaaSamples)
{
size = s;
renderContext = context;
+ samples = msaaSamples;
depthStencil = new QSSGRenderTexture2D(renderContext);
- depthStencil->setTextureData(QSSGByteView(), 0, size.width(), size.height(), QSSGRenderTextureFormat::Depth24Stencil8);
+ if (samples > 1)
+ depthStencil->setTextureDataMultisample(samples, size.width(), size.height(), QSSGRenderTextureFormat::Depth24Stencil8);
+ else
+ depthStencil->setTextureData(QSSGByteView(), 0, size.width(), size.height(), QSSGRenderTextureFormat::Depth24Stencil8);
color0 = new QSSGRenderTexture2D(renderContext);
- color0->setTextureData(QSSGByteView(), 0, size.width(), size.height(), QSSGRenderTextureFormat::RGBA8);
+ if (samples > 1)
+ color0->setTextureDataMultisample(samples, size.width(), size.height(), QSSGRenderTextureFormat::RGBA8);
+ else
+ color0->setTextureData(QSSGByteView(), 0, size.width(), size.height(), QSSGRenderTextureFormat::RGBA8);
fbo = new QSSGRenderFrameBuffer(renderContext);
- fbo->attach(QSSGRenderFrameBufferAttachment::Color0, color0);
- fbo->attach(QSSGRenderFrameBufferAttachment::DepthStencil, depthStencil);
+ fbo->attach(QSSGRenderFrameBufferAttachment::Color0, color0, color0->target());
+ fbo->attach(QSSGRenderFrameBufferAttachment::DepthStencil, depthStencil, depthStencil->target());
}
QQuick3DSceneRenderer::FramebufferObject::~FramebufferObject()
diff --git a/src/quick3d/qquick3dscenerenderer_p.h b/src/quick3d/qquick3dscenerenderer_p.h
index 891c47a5..31e75584 100644
--- a/src/quick3d/qquick3dscenerenderer_p.h
+++ b/src/quick3d/qquick3dscenerenderer_p.h
@@ -61,13 +61,15 @@ class QQuick3DSceneRenderer
{
public:
struct FramebufferObject {
- FramebufferObject(const QSize &s, const QSSGRef<QSSGRenderContext> &context);
+ FramebufferObject(const QSize &s, const QSSGRef<QSSGRenderContext> &context,
+ int msaaSamples = 1);
~FramebufferObject();
QSize size;
QSSGRef<QSSGRenderContext> renderContext;
QSSGRef<QSSGRenderFrameBuffer> fbo;
QSSGRef<QSSGRenderTexture2D> color0;
QSSGRef<QSSGRenderTexture2D> depthStencil;
+ int samples;
};
QQuick3DSceneRenderer(QWindow *window);
@@ -94,11 +96,15 @@ private:
void *data = nullptr;
bool m_layerSizeIsDirty = true;
QWindow *m_window = nullptr;
+ FramebufferObject *m_multisampleFbo = nullptr;
+ FramebufferObject *m_supersampleFbo = nullptr;
FramebufferObject *m_fbo = nullptr;
QSSGRenderNode *m_sceneRootNode = nullptr;
QSSGRenderNode *m_referencedRootNode = nullptr;
+ const int SSAA_Multiplier = 2;
+
friend class SGFramebufferObjectNode;
friend class QQuick3DSGRenderNode;
friend class QQuick3DSGDirectRenderer;
diff --git a/src/quick3d/qquick3dviewport.cpp b/src/quick3d/qquick3dviewport.cpp
index 5bcbe98b..1b3e43ee 100644
--- a/src/quick3d/qquick3dviewport.cpp
+++ b/src/quick3d/qquick3dviewport.cpp
@@ -436,26 +436,46 @@ void QQuick3DViewport::setEnableWireframeMode(bool enableWireframeMode)
update();
}
-static QSurfaceFormat findIdealGLVersion()
+static QSurfaceFormat findIdealGLVersion(int samples)
{
QSurfaceFormat fmt;
+ int defaultSamples = fmt.samples();
+ const bool multisampling = samples > 1;
fmt.setProfile(QSurfaceFormat::CoreProfile);
// Advanced: Try 4.3 core (so we get compute shaders for instance)
fmt.setVersion(4, 3);
+ fmt.setSamples(multisampling ? samples : defaultSamples);
QOpenGLContext ctx;
ctx.setFormat(fmt);
if (ctx.create() && ctx.format().version() >= qMakePair(4, 3)) {
qDebug("Requesting OpenGL 4.3 core context succeeded");
return ctx.format();
+ } else if (multisampling) {
+ // try without multisampling
+ fmt.setSamples(defaultSamples);
+ ctx.setFormat(fmt);
+ if (ctx.create() && ctx.format().version() >= qMakePair(4, 3)) {
+ qDebug("Requesting OpenGL 4.3 core context succeeded without multisampling");
+ return ctx.format();
+ }
}
// Basic: Stick with 3.3 for now to keep less fortunate, Mesa-based systems happy
fmt.setVersion(3, 3);
+ fmt.setSamples(multisampling ? samples : defaultSamples);
ctx.setFormat(fmt);
if (ctx.create() && ctx.format().version() >= qMakePair(3, 3)) {
qDebug("Requesting OpenGL 3.3 core context succeeded");
return ctx.format();
+ } else if (multisampling) {
+ // try without multisampling
+ fmt.setSamples(defaultSamples);
+ ctx.setFormat(fmt);
+ if (ctx.create() && ctx.format().version() >= qMakePair(3, 3)) {
+ qDebug("Requesting OpenGL 3.3 core context succeeded without multisampling");
+ return ctx.format();
+ }
}
qDebug("Impending doom");
@@ -485,13 +505,16 @@ static bool isBlackListedES3Driver(QOpenGLContext &ctx)
}
-static QSurfaceFormat findIdealGLESVersion()
+static QSurfaceFormat findIdealGLESVersion(int samples)
{
QSurfaceFormat fmt;
+ int defaultSamples = fmt.samples();
+ const bool multisampling = samples > 1;
// Advanced: Try 3.1 (so we get compute shaders for instance)
fmt.setVersion(3, 1);
fmt.setRenderableType(QSurfaceFormat::OpenGLES);
+ fmt.setSamples(multisampling ? samples : defaultSamples);
QOpenGLContext ctx;
ctx.setFormat(fmt);
@@ -504,38 +527,62 @@ static QSurfaceFormat findIdealGLESVersion()
if (ctx.create() && ctx.format().version() >= qMakePair(3, 1)) {
qDebug("Requesting OpenGL ES 3.1 context succeeded");
return ctx.format();
+ } else if (multisampling) {
+ fmt.setSamples(defaultSamples);
+ ctx.setFormat(fmt);
+ if (ctx.create() && ctx.format().version() >= qMakePair(3, 1)) {
+ qDebug("Requesting OpenGL ES 3.1 context succeeded without multisampling");
+ return ctx.format();
+ }
}
// Basic: OpenGL ES 3.0 is a hard requirement at the moment since we can
// only generate 300 es shaders, uniform buffers are mandatory.
fmt.setVersion(3, 0);
+ fmt.setSamples(multisampling ? samples : defaultSamples);
ctx.setFormat(fmt);
qDebug("Testing OpenGL ES 3.0");
if (ctx.create() && ctx.format().version() >= qMakePair(3, 0) && !isBlackListedES3Driver(ctx)) {
qDebug("Requesting OpenGL ES 3.0 context succeeded");
return ctx.format();
+ } else if (multisampling) {
+ fmt.setSamples(defaultSamples);
+ ctx.setFormat(fmt);
+ if (ctx.create() && ctx.format().version() >= qMakePair(3, 0)
+ && !isBlackListedES3Driver(ctx)) {
+ qDebug("Requesting OpenGL ES 3.0 context succeeded without multisampling");
+ return ctx.format();
+ }
}
fmt.setVersion(2, 0);
+ fmt.setSamples(multisampling ? samples : defaultSamples);
ctx.setFormat(fmt);
qDebug("Testing OpenGL ES 2.0");
if (ctx.create()) {
qDebug("Requesting OpenGL ES 2.0 context succeeded");
return fmt;
+ } else if (multisampling) {
+ fmt.setSamples(defaultSamples);
+ ctx.setFormat(fmt);
+ if (ctx.create()) {
+ qDebug("Requesting OpenGL ES 2.0 context succeeded without multisampling");
+ return fmt;
+ }
}
qDebug("Impending doom");
return fmt;
}
-QSurfaceFormat QQuick3DViewport::idealSurfaceFormat()
+QSurfaceFormat QQuick3DViewport::idealSurfaceFormat(int samples)
{
- static const QSurfaceFormat f = [] {
+ static const QSurfaceFormat f = [samples] {
QSurfaceFormat fmt;
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { // works in dynamic gl builds too because there's a qguiapp already
- fmt = findIdealGLVersion();
+ fmt = findIdealGLVersion(samples);
} else {
- fmt = findIdealGLESVersion();
+ fmt = findIdealGLESVersion(samples);
}
fmt.setDepthBufferSize(24);
fmt.setStencilBufferSize(8);
diff --git a/src/quick3d/qquick3dviewport_p.h b/src/quick3d/qquick3dviewport_p.h
index e25678e3..38b327fe 100644
--- a/src/quick3d/qquick3dviewport_p.h
+++ b/src/quick3d/qquick3dviewport_p.h
@@ -97,7 +97,7 @@ public:
QSGTextureProvider *textureProvider() const override;
void releaseResources() override;
- static QSurfaceFormat idealSurfaceFormat();
+ static QSurfaceFormat idealSurfaceFormat(int samples = -1);
Q_INVOKABLE QVector3D mapFrom3DScene(const QVector3D &scenePos) const;
Q_INVOKABLE QVector3D mapTo3DScene(const QVector3D &viewPos) const;
diff --git a/src/render/qssgrendertexturebase_p.h b/src/render/qssgrendertexturebase_p.h
index 68d17ecc..112eec38 100644
--- a/src/render/qssgrendertexturebase_p.h
+++ b/src/render/qssgrendertexturebase_p.h
@@ -123,6 +123,7 @@ public:
bool isMultisampleTexture() const { return (m_texTarget == QSSGRenderTextureTargetType::Texture2D_MS); }
qint32 sampleCount() const { return m_sampleCount; }
bool isImmutable() const { return m_immutable; }
+ QSSGRenderTextureTargetType target() const { return m_texTarget; }
/**
* @brief Bind a texture for shader access
diff --git a/src/runtimerender/rendererimpl/qssgrendererimpllayerrenderdata.cpp b/src/runtimerender/rendererimpl/qssgrendererimpllayerrenderdata.cpp
index 5ea2e146..74706d37 100644
--- a/src/runtimerender/rendererimpl/qssgrendererimpllayerrenderdata.cpp
+++ b/src/runtimerender/rendererimpl/qssgrendererimpllayerrenderdata.cpp
@@ -1753,9 +1753,7 @@ void QSSGLayerRenderData::runnableRenderToViewport(const QSSGRef<QSSGRenderFrame
theContext->setRenderTarget(theFB);
// Multisampling
- if (sampleCount > 1) {
- theContext->setMultisampleEnabled(true);
- }
+ theContext->setMultisampleEnabled(sampleCount > 1 ? true : false);
// Start Operations on Viewport
theContext->setViewport(layerPrepResult->viewport().toRect());
diff --git a/tests/manual/runtimerender/testbed/renderwindow.cpp b/tests/manual/runtimerender/testbed/renderwindow.cpp
index 6d0b9476..bd4400ed 100644
--- a/tests/manual/runtimerender/testbed/renderwindow.cpp
+++ b/tests/manual/runtimerender/testbed/renderwindow.cpp
@@ -265,6 +265,6 @@ void RenderWindow::buildTestScene()
m_layer->addChild(*m_cube);
// Default Material
- auto material = new QSSGRenderDefaultMaterial();
+ auto material = new QSSGRenderDefaultMaterial(QSSGRenderGraphObject::Type::DefaultMaterial);
m_cube->materials.append(material);
}