diff --git a/src/RiveQtQuickItem/renderer/riveqtfactory.cpp b/src/RiveQtQuickItem/renderer/riveqtfactory.cpp index 0f3c70a..4086ffc 100644 --- a/src/RiveQtQuickItem/renderer/riveqtfactory.cpp +++ b/src/RiveQtQuickItem/renderer/riveqtfactory.cpp @@ -28,18 +28,15 @@ RiveQSGRenderNode *RiveQtFactory::renderNode(QQuickWindow *window, std::weak_ptr case QSGRendererInterface::GraphicsApi::Direct3D11Rhi: { QSGRendererInterface *renderInterface = window->rendererInterface(); QRhi *rhi = static_cast(renderInterface->getResource(window, QSGRendererInterface::RhiResource)); + if (rhi->isFeatureSupported(QRhi::MultisampleTexture) && rhi->isFeatureSupported(QRhi::MultisampleRenderBuffer)) { - auto sampleCounts = rhi->supportedSampleCounts(); - - if (rhi->isFeatureSupported(QRhi::MultisampleTexture) && rhi->isFeatureSupported(QRhi::MultisampleRenderBuffer) - && sampleCounts.contains(RiveQSGRenderNode::MULTISAMPLE_COUNT)) { auto node = new RiveQSGRHIRenderNode(window, artboardInstance, geometry); node->setFillMode(m_renderSettings.fillMode); node->setPostprocessingMode(m_renderSettings.postprocessingMode); return node; } else { qCritical(rqqpFactory) - << "RiveQtQuickPlign requires 4x multisample support. The hardware does not support 4x multisampling. Switch to " + << "RiveQtQuickPlign requires multisample support. The hardware does not support multisampling. Switch to " "SoftwareRenderer."; return nullptr; } diff --git a/src/RiveQtQuickItem/riveqsgrendernode.h b/src/RiveQtQuickItem/riveqsgrendernode.h index 163d61e..eff6f00 100644 --- a/src/RiveQtQuickItem/riveqsgrendernode.h +++ b/src/RiveQtQuickItem/riveqsgrendernode.h @@ -28,8 +28,6 @@ class RiveQSGBaseNode virtual void setArtboardRect(const QRectF &bounds); - static const int MULTISAMPLE_COUNT { 4 }; - protected: std::weak_ptr m_artboardInstance; QRectF m_rect; diff --git a/src/RiveQtQuickItem/riveqsgrhirendernode.cpp b/src/RiveQtQuickItem/riveqsgrhirendernode.cpp index bb4f293..0cf428f 100644 --- a/src/RiveQtQuickItem/riveqsgrhirendernode.cpp +++ b/src/RiveQtQuickItem/riveqsgrhirendernode.cpp @@ -19,6 +19,11 @@ RiveQSGRHIRenderNode::RiveQSGRHIRenderNode(QQuickWindow *window, std::weak_ptrrendererInterface(); + QRhi *rhi = static_cast(renderInterface->getResource(m_window, QSGRendererInterface::RhiResource)); + auto sampleCounts = rhi->supportedSampleCounts(); + m_samples = sampleCounts.last(); + QFile file; file.setFileName(":/shaders/qt6/finalDraw.vert.qsb"); file.open(QFile::ReadOnly); @@ -99,15 +104,6 @@ void RiveQSGRHIRenderNode::setRect(const QRectF &bounds) m_vertices.append(QVector2D(bounds.x() + bounds.width(), bounds.y())); m_vertices.append(QVector2D(bounds.x() + bounds.width(), bounds.y() + bounds.height())); - resetResources(); - - RiveQSGBaseNode::setRect(bounds); - - markDirty(QSGNode::DirtyGeometry); -} - -void RiveQSGRHIRenderNode::resetResources() -{ // todo this is not yet fully correct. Resize is super expensive due to resource destruction // TODO: maybe we should only do this in case the texture gets larger and stays larger for some time // that may cost us quality but will save us a lot of issues @@ -143,6 +139,9 @@ void RiveQSGRHIRenderNode::resetResources() if (m_postprocessing) { m_postprocessing->cleanup(); } + + RiveQSGBaseNode::setRect(bounds); + markDirty(QSGNode::DirtyGeometry); } void RiveQSGRHIRenderNode::setFillMode(const RiveRenderSettings::FillMode mode) @@ -349,20 +348,17 @@ void RiveQSGRHIRenderNode::prepare() QRhiCommandBuffer *commandBuffer = swapChain->currentFrameCommandBuffer(); if (!m_stencilClippingBuffer) { - m_stencilClippingBuffer = - rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(m_rect.width() * m_pixelRatio, m_rect.height() * m_pixelRatio), - RiveQSGRenderNode::MULTISAMPLE_COUNT); + m_stencilClippingBuffer = rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, + QSize(m_rect.width() * m_pixelRatio, m_rect.height() * m_pixelRatio), m_samples); m_stencilClippingBuffer->create(); m_cleanupList.append(m_stencilClippingBuffer); } - bool textureCreated = - m_renderSurfaceA.create(rhi, RiveQSGRenderNode::MULTISAMPLE_COUNT, - QSize(m_rect.width() * m_pixelRatio, m_rect.height() * m_pixelRatio), m_stencilClippingBuffer); - m_renderSurfaceB.create(rhi, RiveQSGRenderNode::MULTISAMPLE_COUNT, QSize(m_rect.width() * m_pixelRatio, m_rect.height() * m_pixelRatio), - m_stencilClippingBuffer); - m_renderSurfaceIntern.create(rhi, RiveQSGRenderNode::MULTISAMPLE_COUNT, - QSize(m_rect.width() * m_pixelRatio, m_rect.height() * m_pixelRatio), m_stencilClippingBuffer, {}); + bool textureCreated = m_renderSurfaceA.create(rhi, m_samples, QSize(m_rect.width() * m_pixelRatio, m_rect.height() * m_pixelRatio), + m_stencilClippingBuffer); + m_renderSurfaceB.create(rhi, m_samples, QSize(m_rect.width() * m_pixelRatio, m_rect.height() * m_pixelRatio), m_stencilClippingBuffer); + m_renderSurfaceIntern.create(rhi, m_samples, QSize(m_rect.width() * m_pixelRatio, m_rect.height() * m_pixelRatio), + m_stencilClippingBuffer, {}); // only set the renderSurface to A in case we created a new texture if (textureCreated) { @@ -405,7 +401,7 @@ void RiveQSGRHIRenderNode::prepare() // only for bindings if (!m_dummyTexture) { - m_dummyTexture = rhi->newTexture(QRhiTexture::BGRA8, QSize(1, 1), RiveQSGRenderNode::MULTISAMPLE_COUNT); + m_dummyTexture = rhi->newTexture(QRhiTexture::BGRA8, QSize(1, 1), m_samples); m_cleanupList.append(m_dummyTexture); m_dummyTexture->create(); } @@ -457,13 +453,13 @@ void RiveQSGRHIRenderNode::prepare() } if (!m_drawPipeline) { - m_drawPipeline = createDrawPipeline(rhi, RiveQSGRenderNode::MULTISAMPLE_COUNT, true, true, m_renderSurfaceA.desc, - QRhiGraphicsPipeline::Triangles, m_pathShader, m_drawPipelineResourceBindings); + m_drawPipeline = createDrawPipeline(rhi, m_samples, true, true, m_renderSurfaceA.desc, QRhiGraphicsPipeline::Triangles, + m_pathShader, m_drawPipelineResourceBindings); } if (!m_drawPipelineIntern) { - m_drawPipelineIntern = createDrawPipeline(rhi, RiveQSGRenderNode::MULTISAMPLE_COUNT, false, true, m_renderSurfaceIntern.desc, - QRhiGraphicsPipeline::Triangles, m_pathShader, m_drawPipelineResourceBindings); + m_drawPipelineIntern = createDrawPipeline(rhi, m_samples, false, true, m_renderSurfaceIntern.desc, QRhiGraphicsPipeline::Triangles, + m_pathShader, m_drawPipelineResourceBindings); } if (!m_blendPipeline) { @@ -574,7 +570,7 @@ void RiveQSGRHIRenderNode::prepare() } if (m_postprocessing) { - m_postprocessing->initializePostprocessingPipeline(rhi, commandBuffer, RiveQSGRenderNode::MULTISAMPLE_COUNT, + m_postprocessing->initializePostprocessingPipeline(rhi, commandBuffer, m_samples, QSize(m_rect.width() * m_pixelRatio, m_rect.height() * m_pixelRatio), m_renderSurfaceA.texture, m_renderSurfaceB.texture); } @@ -636,9 +632,8 @@ void RiveQSGRHIRenderNode::prepare() } if (!m_finalDrawPipeline) { - m_finalDrawPipeline = - createDrawPipeline(rhi, RiveQSGRenderNode::MULTISAMPLE_COUNT, true, false, QSGRenderNodePrivate::get(this)->m_rt.rpDesc, - QRhiGraphicsPipeline::TriangleStrip, m_finalDrawShader, m_finalDrawResourceBindings); + m_finalDrawPipeline = createDrawPipeline(rhi, m_samples, true, false, QSGRenderNodePrivate::get(this)->m_rt.rpDesc, + QRhiGraphicsPipeline::TriangleStrip, m_finalDrawShader, m_finalDrawResourceBindings); } QMatrix4x4 mvp = *projectionMatrix(); @@ -652,7 +647,7 @@ void RiveQSGRHIRenderNode::prepare() int flipped = rhi->isYUpInFramebuffer() ? 1 : 0; int useTextureNumber = 0; - int sampleCount = RiveQSGRenderNode::MULTISAMPLE_COUNT; + int sampleCount = m_samples; if (!isCurrentRenderBufferA()) { useTextureNumber = 1; @@ -708,7 +703,7 @@ QRhiGraphicsPipeline *RiveQSGRHIRenderNode::createClipPipeline(QRhi *rhi, QRhiRe clipPipeLine->setTopology(QRhiGraphicsPipeline::Triangles); clipPipeLine->setVertexInputLayout(inputLayout); clipPipeLine->setRenderPassDescriptor(renderPassDescriptor); - clipPipeLine->setSampleCount(RiveQSGRenderNode::MULTISAMPLE_COUNT); + clipPipeLine->setSampleCount(m_samples); clipPipeLine->setShaderResourceBindings(bindings); clipPipeLine->create(); @@ -796,7 +791,7 @@ QRhiGraphicsPipeline *RiveQSGRHIRenderNode::createBlendPipeline(QRhi *rhi, QRhiR blendPipeLine->setStencilTest(false); blendPipeLine->setShaderResourceBindings(bindings); blendPipeLine->setShaderStages(m_blendShaders.cbegin(), m_blendShaders.cend()); - blendPipeLine->setSampleCount(RiveQSGRenderNode::MULTISAMPLE_COUNT); + blendPipeLine->setSampleCount(m_samples); QRhiVertexInputLayout inputLayout; inputLayout.setBindings({ { sizeof(QVector2D) }, diff --git a/src/RiveQtQuickItem/riveqsgrhirendernode.h b/src/RiveQtQuickItem/riveqsgrhirendernode.h index 4858715..89d6d9c 100644 --- a/src/RiveQtQuickItem/riveqsgrhirendernode.h +++ b/src/RiveQtQuickItem/riveqsgrhirendernode.h @@ -159,11 +159,10 @@ class RiveQSGRHIRenderNode : public RiveQSGRenderNode PostprocessingSMAA *m_postprocessing { nullptr }; -private: - void resetResources(); +private: float m_pixelRatio { 1.0f }; - + int m_samples { 4 }; QRhiGraphicsPipeline *createBlendPipeline(QRhi *rhi, QRhiRenderPassDescriptor *renderPass, QRhiShaderResourceBindings *bindings); QRhiGraphicsPipeline *createClipPipeline(QRhi *rhi, QRhiRenderPassDescriptor *renderPassDescriptor, QRhiShaderResourceBindings *bindings); diff --git a/src/RiveQtQuickItem/shaders/qt6/edges.vert b/src/RiveQtQuickItem/shaders/qt6/edges.vert index e0ae902..3c3c95e 100644 --- a/src/RiveQtQuickItem/shaders/qt6/edges.vert +++ b/src/RiveQtQuickItem/shaders/qt6/edges.vert @@ -41,7 +41,6 @@ layout(location = 1) out vec4 vOffset[3]; layout(std140, binding = 0) uniform buf { vec2 resolution; int flip; - int sampleCount; } ubuf; out gl_PerVertex { vec4 gl_Position; }; @@ -52,7 +51,7 @@ void main() { v_texcoord = vec2(texcoord.x, texcoord.y); if (ubuf.flip != 0) v_texcoord.y = 1.0 - v_texcoord.y; - + vOffset[0] = mad(SMAA_RT_METRICS.xyxy, vec4(-1.0, 0.0, 0.0, -1.0), v_texcoord.xyxy); vOffset[1] = mad(SMAA_RT_METRICS.xyxy, vec4(1.0, 0.0, 0.0, 1.0), v_texcoord.xyxy); vOffset[2] = mad(SMAA_RT_METRICS.xyxy, vec4(-2.0, 0.0, 0.0, -2.0), v_texcoord.xyxy); diff --git a/src/RiveQtQuickItem/shaders/qt6/smaa-blend.vert b/src/RiveQtQuickItem/shaders/qt6/smaa-blend.vert index 9934a19..b68de71 100644 --- a/src/RiveQtQuickItem/shaders/qt6/smaa-blend.vert +++ b/src/RiveQtQuickItem/shaders/qt6/smaa-blend.vert @@ -41,7 +41,6 @@ layout(location = 1) out vec4 vOffset; layout(std140, binding = 0) uniform buf { vec2 resolution; int flip; - int sampleCount; } ubuf; out gl_PerVertex { vec4 gl_Position; }; @@ -56,4 +55,4 @@ void main() { vOffset = mad(SMAA_RT_METRICS.xyxy, vec4(1.0, 0.0, 0.0, 1.0), v_texcoord.xyxy); gl_Position = position; -} +} \ No newline at end of file diff --git a/src/RiveQtQuickItem/shaders/qt6/smaa-weights.vert b/src/RiveQtQuickItem/shaders/qt6/smaa-weights.vert index 0cc8e24..c7a9eaf 100644 --- a/src/RiveQtQuickItem/shaders/qt6/smaa-weights.vert +++ b/src/RiveQtQuickItem/shaders/qt6/smaa-weights.vert @@ -50,7 +50,6 @@ layout(location = 2) out vec4 vOffset[3]; layout(std140, binding = 0) uniform buf { vec2 resolution; int flip; - int sampleCount; } ubuf; void main() { @@ -61,7 +60,7 @@ void main() { v_texcoord.y = 1.0 - v_texcoord.y; vPixCoord = v_texcoord * SMAA_RT_METRICS.zw; - + // We will use these offsets for the searches later on (see @PSEUDO_GATHER4): vOffset[0] = mad(SMAA_RT_METRICS.xyxy, vec4(-0.25, -0.125, 1.25, -0.125), v_texcoord.xyxy); vOffset[1] = mad(SMAA_RT_METRICS.xyxy, vec4(-0.125, -0.25, -0.125, 1.25), v_texcoord.xyxy); @@ -74,4 +73,4 @@ void main() { ); gl_Position = position; -} +} \ No newline at end of file