D3D12: Recursive layer support

To avoid using the same color buffer both as a shader resource and as a
render target, recursive layers add a second render target and just play
ping-pong with them. Multisampling does not need this since rendering
happens into a MS buffer while shader access uses a separate, non-MS color
buffer.

Change-Id: I6fd65318f69390d7af9ca6763d1d9fe2329780aa
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
Laszlo Agocs 2016-04-20 11:42:23 +02:00
parent 9c19298510
commit 27d23848a3
7 changed files with 49 additions and 21 deletions

View File

@ -485,9 +485,9 @@ SIZE_T QSGD3D12Engine::textureSRV(uint id) const
return d->textureSRV(id);
}
void QSGD3D12Engine::activateTexture(uint id)
void QSGD3D12Engine::useTexture(uint id)
{
d->activateTexture(id);
d->useTexture(id);
}
uint QSGD3D12Engine::genRenderTarget()
@ -505,9 +505,14 @@ void QSGD3D12Engine::releaseRenderTarget(uint id)
d->releaseRenderTarget(id);
}
void QSGD3D12Engine::activateRenderTargetAsTexture(uint id)
void QSGD3D12Engine::useRenderTargetAsTexture(uint id)
{
d->activateRenderTargetAsTexture(id);
d->useRenderTargetAsTexture(id);
}
uint QSGD3D12Engine::activeRenderTarget() const
{
return d->activeRenderTarget();
}
QSGRendererInterface::GraphicsAPI QSGD3D12Engine::graphicsAPI() const
@ -2464,7 +2469,7 @@ SIZE_T QSGD3D12EnginePrivate::textureSRV(uint id) const
return textures[idx].srv.ptr;
}
void QSGD3D12EnginePrivate::activateTexture(uint id)
void QSGD3D12EnginePrivate::useTexture(uint id)
{
if (!inFrame) {
qWarning("%s: Cannot be called outside begin/endFrame", __FUNCTION__);
@ -2748,7 +2753,7 @@ void QSGD3D12EnginePrivate::releaseRenderTarget(uint id)
rt.flags &= ~RenderTarget::EntryInUse;
}
void QSGD3D12EnginePrivate::activateRenderTargetAsTexture(uint id)
void QSGD3D12EnginePrivate::useRenderTargetAsTexture(uint id)
{
if (!inFrame) {
qWarning("%s: Cannot be called outside begin/endFrame", __FUNCTION__);

View File

@ -341,12 +341,13 @@ public:
void queueTextureUpload(uint id, const QVector<QImage> &images, const QVector<QPoint> &dstPos);
void releaseTexture(uint id);
SIZE_T textureSRV(uint id) const;
void activateTexture(uint id);
void useTexture(uint id);
uint genRenderTarget();
void createRenderTarget(uint id, const QSize &size, const QVector4D &clearColor, uint samples);
void releaseRenderTarget(uint id);
void activateRenderTargetAsTexture(uint id);
void useRenderTargetAsTexture(uint id);
uint activeRenderTarget() const;
// QSGRendererInterface
GraphicsAPI graphicsAPI() const override;

View File

@ -172,12 +172,13 @@ public:
void queueTextureUpload(uint id, const QVector<QImage> &images, const QVector<QPoint> &dstPos);
void releaseTexture(uint id);
SIZE_T textureSRV(uint id) const;
void activateTexture(uint id);
void useTexture(uint id);
uint genRenderTarget();
void createRenderTarget(uint id, const QSize &size, const QVector4D &clearColor, uint samples);
void releaseRenderTarget(uint id);
void activateRenderTargetAsTexture(uint id);
void useRenderTargetAsTexture(uint id);
uint activeRenderTarget() const { return currentRenderTarget; }
void *getResource(QSGRendererInterface::Resource resource) const;

View File

@ -173,7 +173,7 @@ int QSGD3D12GlyphCache::maxTextureHeight() const
void QSGD3D12GlyphCache::activateTexture()
{
if (m_id)
m_engine->activateTexture(m_id);
m_engine->useTexture(m_id);
}
QSize QSGD3D12GlyphCache::currentSize() const

View File

@ -105,9 +105,16 @@ void QSGD3D12Layer::bind()
if (Q_UNLIKELY(debug_render()))
qDebug("layer %p bind rt=%u", this, m_rt);
// ###
QSGD3D12Engine *engine = m_rc->engine();
Q_ASSERT(m_rt);
m_rc->engine()->activateRenderTargetAsTexture(m_rt);
#ifndef QT_NO_DEBUG
// Should not use the color buffer as a texture while it is the current render target.
if (!m_recursive && engine->activeRenderTarget() == m_rt && engine->windowSamples() == 1)
qWarning("ShaderEffectSource: \'recursive\' must be set to true when rendering recursively.");
#endif
engine->useRenderTargetAsTexture(m_rt);
}
// QSGDynamicTexture
@ -268,6 +275,11 @@ void QSGD3D12Layer::resetRenderTarget()
m_rc->engine()->releaseRenderTarget(m_rt);
m_rt = 0;
if (m_secondaryRT) {
m_rc->engine()->releaseRenderTarget(m_secondaryRT);
m_secondaryRT = 0;
}
}
void QSGD3D12Layer::updateContent()
@ -297,17 +309,16 @@ void QSGD3D12Layer::updateContent()
m_renderer->setDevicePixelRatio(m_dpr);
m_renderer->setRootNode(static_cast<QSGRootNode *>(root));
if (!m_rt || m_rtSize != m_size) {
QSGD3D12Engine *engine = m_rc->engine();
// ### recursive
QSGD3D12Engine *engine = m_rc->engine();
const uint sampleCount = engine->windowSamples();
const QVector4D clearColor;
if (!m_rt || m_rtSize != m_size) {
if (m_rt)
resetRenderTarget();
m_rt = engine->genRenderTarget();
m_rtSize = m_size;
const uint sampleCount = engine->windowSamples();
const QVector4D clearColor;
if (Q_UNLIKELY(debug_render()))
qDebug("new render target for layer %p, size=%dx%d, samples=%d",
@ -319,6 +330,11 @@ void QSGD3D12Layer::updateContent()
// handled internally in the engine, no need to worry about it here.
}
if (m_recursive && !m_secondaryRT && sampleCount == 1) {
m_secondaryRT = engine->genRenderTarget();
engine->createRenderTarget(m_secondaryRT, m_rtSize, clearColor, sampleCount);
}
m_dirtyTexture = false;
m_renderer->setDeviceRect(m_size);
@ -330,8 +346,12 @@ void QSGD3D12Layer::updateContent()
m_renderer->setProjectionMatrixToRect(mirrored);
m_renderer->setClearColor(Qt::transparent);
// ### recursive
m_renderer->renderScene(m_rt);
if (!m_recursive || sampleCount > 1) {
m_renderer->renderScene(m_rt);
} else {
m_renderer->renderScene(m_secondaryRT);
qSwap(m_rt, m_secondaryRT);
}
if (m_recursive)
markDirtyTexture(); // Continuously update if 'live' and 'recursive'.

View File

@ -98,6 +98,7 @@ private:
QSGD3D12RenderContext *m_rc;
uint m_rt = 0;
uint m_secondaryRT = 0;
QSize m_rtSize;
QSize m_size;
QRectF m_rect;

View File

@ -122,7 +122,7 @@ void QSGD3D12Texture::bind()
// Here we know that the texture is going to be used in the current frame
// by the next draw call. Notify the engine so that it can wait for
// possible pending uploads and set up the pipeline accordingly.
m_engine->activateTexture(m_id);
m_engine->useTexture(m_id);
}
SIZE_T QSGD3D12Texture::srv() const