diff options
Diffstat (limited to 'src/gui/rhi')
-rw-r--r-- | src/gui/rhi/qrhi.cpp | 59 | ||||
-rw-r--r-- | src/gui/rhi/qrhi_p.h | 17 | ||||
-rw-r--r-- | src/gui/rhi/qrhi_p_p.h | 7 | ||||
-rw-r--r-- | src/gui/rhi/qrhid3d11.cpp | 11 | ||||
-rw-r--r-- | src/gui/rhi/qrhid3d11_p_p.h | 9 | ||||
-rw-r--r-- | src/gui/rhi/qrhigles2.cpp | 17 | ||||
-rw-r--r-- | src/gui/rhi/qrhigles2_p_p.h | 9 | ||||
-rw-r--r-- | src/gui/rhi/qrhimetal.mm | 151 | ||||
-rw-r--r-- | src/gui/rhi/qrhimetal_p_p.h | 10 | ||||
-rw-r--r-- | src/gui/rhi/qrhinull.cpp | 8 | ||||
-rw-r--r-- | src/gui/rhi/qrhinull_p_p.h | 9 | ||||
-rw-r--r-- | src/gui/rhi/qrhivulkan.cpp | 41 | ||||
-rw-r--r-- | src/gui/rhi/qrhivulkan_p_p.h | 9 |
13 files changed, 239 insertions, 118 deletions
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp index a9c6835687..f0bf19bd91 100644 --- a/src/gui/rhi/qrhi.cpp +++ b/src/gui/rhi/qrhi.cpp @@ -1652,7 +1652,7 @@ QRhiTextureUploadDescription::QRhiTextureUploadDescription(const QRhiTextureUplo Constructs a texture upload description with the specified \a list of entries. \note \a list can also contain multiple QRhiTextureUploadEntry elements - with the the same layer and level. This makes sense when those uploads are + with the same layer and level. This makes sense when those uploads are partial, meaning their subresource description has a source size or image smaller than the subresource dimensions, and can be more efficient than issuing separate uploadTexture()'s. @@ -2297,11 +2297,10 @@ bool QRhiTexture::buildFrom(QRhiTexture::NativeTexture src) */ QRhiSampler::QRhiSampler(QRhiImplementation *rhi, Filter magFilter_, Filter minFilter_, Filter mipmapMode_, - AddressMode u_, AddressMode v_) + AddressMode u_, AddressMode v_, AddressMode w_) : QRhiResource(rhi), m_magFilter(magFilter_), m_minFilter(minFilter_), m_mipmapMode(mipmapMode_), - m_addressU(u_), m_addressV(v_), - m_addressW(QRhiSampler::ClampToEdge), + m_addressU(u_), m_addressV(v_), m_addressW(w_), m_compareOp(QRhiSampler::Never) { } @@ -3506,7 +3505,7 @@ QRhiResource::Type QRhiGraphicsPipeline::resourceType() const \l{QSurfaceFormat::sRGBColorSpace}{sRGBColorSpace} on the QSurfaceFormat of the QWindow in addition. - \value UsedAsTransferSource Indicates the the swapchain will be used as the + \value UsedAsTransferSource Indicates the swapchain will be used as the source of a readback in QRhiResourceUpdateBatch::readBackTexture(). \value NoVSync Requests disabling waiting for vertical sync, also avoiding @@ -3623,7 +3622,7 @@ QRhiResource::Type QRhiSwapChain::resourceType() const \fn QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget() \return a render target that can used with beginPass() in order to render - the the swapchain's current backbuffer. Only valid within a + the swapchain's current backbuffer. Only valid within a QRhi::beginFrame() - QRhi::endFrame() block where beginFrame() was called with this swapchain. @@ -4449,7 +4448,7 @@ void QRhiResourceUpdateBatch::generateMips(QRhiTexture *tex, int layer) recorded. \note the return value is not owned by the caller and must never be - destroyed. Instead, the batch is returned the the pool for reuse by passing + destroyed. Instead, the batch is returned the pool for reuse by passing it to QRhiCommandBuffer::beginPass(), QRhiCommandBuffer::endPass(), or QRhiCommandBuffer::resourceUpdate(), or by calling QRhiResourceUpdateBatch::release() on it. @@ -5059,13 +5058,24 @@ bool QRhi::isYUpInNDC() const } /*! - \return \c true if the underlying graphics API uses depth 0 - 1 in clip - space. + \return \c true if the underlying graphics API uses depth range [0, 1] in + clip space. - In practice this is \c false for OpenGL only. + In practice this is \c false for OpenGL only, because OpenGL uses a + post-projection depth range of [-1, 1]. (not to be confused with the + NDC-to-window mapping controlled by glDepthRange(), which uses a range of + [0, 1], unless overridden by the QRhiViewport) In some OpenGL versions + glClipControl() could be used to change this, but the OpenGL backend of + QRhi does not use that function as it is not available in OpenGL ES or + OpenGL versions lower than 4.5. \note clipSpaceCorrMatrix() includes the corresponding adjustment in its - returned matrix. + returned matrix. Therefore, many users of QRhi do not need to take any + further measures apart from pre-multiplying their projection matrices with + clipSpaceCorrMatrix(). However, some graphics techniques, such as, some + types of shadow mapping, involve working with and outputting depth values + in the shaders. These will need to query and take the value of this + function into account as appropriate. */ bool QRhi::isClipDepthZeroToOne() const { @@ -5075,11 +5085,15 @@ bool QRhi::isClipDepthZeroToOne() const /*! \return a matrix that can be used to allow applications keep using OpenGL-targeted vertex data and perspective projection matrices (such as, - the ones generated by QMatrix4x4::perspective()), regardless of the - backend. Once \c{this_matrix * mvp} is used instead of just \c mvp, vertex - data with Y up and viewports with depth range 0 - 1 can be used without - considering what backend and so graphics API is going to be used at run - time. + the ones generated by QMatrix4x4::perspective()), regardless of the active + QRhi backend. + + In a typical renderer, once \c{this_matrix * mvp} is used instead of just + \c mvp, vertex data with Y up and viewports with depth range 0 - 1 can be + used without considering what backend (and so graphics API) is going to be + used at run time. This way branching based on isYUpInNDC() and + isClipDepthZeroToOne() can be avoided (although such logic may still become + required when implementing certain advanced graphics techniques). See \l{https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/}{this @@ -5321,16 +5335,19 @@ QRhiTexture *QRhi::newTexture(QRhiTexture::Format format, /*! \return a new sampler with the specified magnification filter \a magFilter, - minification filter \a minFilter, mipmapping mode \a mipmapMpde, and S/T - addressing modes \a u and \a v. + minification filter \a minFilter, mipmapping mode \a mipmapMode, and the + addressing (wrap) modes \a addressU, \a addressV, and \a addressW. \sa QRhiResource::release() */ -QRhiSampler *QRhi::newSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, +QRhiSampler *QRhi::newSampler(QRhiSampler::Filter magFilter, + QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, - QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) + QRhiSampler::AddressMode addressU, + QRhiSampler::AddressMode addressV, + QRhiSampler::AddressMode addressW) { - return d->createSampler(magFilter, minFilter, mipmapMode, u, v); + return d->createSampler(magFilter, minFilter, mipmapMode, addressU, addressV, addressW); } /*! diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h index 3a64835c22..d17112a241 100644 --- a/src/gui/rhi/qrhi_p.h +++ b/src/gui/rhi/qrhi_p.h @@ -850,7 +850,7 @@ public: protected: QRhiSampler(QRhiImplementation *rhi, Filter magFilter_, Filter minFilter_, Filter mipmapMode_, - AddressMode u_, AddressMode v_); + AddressMode u_, AddressMode v_, AddressMode w_); Filter m_magFilter; Filter m_minFilter; Filter m_mipmapMode; @@ -1155,6 +1155,12 @@ public: float lineWidth() const { return m_lineWidth; } void setLineWidth(float width) { m_lineWidth = width; } + int depthBias() const { return m_depthBias; } + void setDepthBias(int bias) { m_depthBias = bias; } + + float slopeScaledDepthBias() const { return m_slopeScaledDepthBias; } + void setSlopeScaledDepthBias(float bias) { m_slopeScaledDepthBias = bias; } + void setShaderStages(std::initializer_list<QRhiShaderStage> list) { m_shaderStages = list; } template<typename InputIterator> void setShaderStages(InputIterator first, InputIterator last) @@ -1193,6 +1199,8 @@ protected: quint32 m_stencilWriteMask = 0xFF; int m_sampleCount = 1; float m_lineWidth = 1.0f; + int m_depthBias = 0; + float m_slopeScaledDepthBias = 0.0f; QVarLengthArray<QRhiShaderStage, 4> m_shaderStages; QRhiVertexInputLayout m_vertexInputLayout; QRhiShaderResourceBindings *m_shaderResourceBindings = nullptr; @@ -1474,9 +1482,12 @@ public: int sampleCount = 1, QRhiTexture::Flags flags = QRhiTexture::Flags()); - QRhiSampler *newSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, + QRhiSampler *newSampler(QRhiSampler::Filter magFilter, + QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, - QRhiSampler::AddressMode u, QRhiSampler::AddressMode v); + QRhiSampler::AddressMode addressU, + QRhiSampler::AddressMode addressV, + QRhiSampler::AddressMode addressW = QRhiSampler::Repeat); QRhiTextureRenderTarget *newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags = QRhiTextureRenderTarget::Flags()); diff --git a/src/gui/rhi/qrhi_p_p.h b/src/gui/rhi/qrhi_p_p.h index baffe28202..4a4c044a29 100644 --- a/src/gui/rhi/qrhi_p_p.h +++ b/src/gui/rhi/qrhi_p_p.h @@ -85,9 +85,12 @@ public: const QSize &pixelSize, int sampleCount, QRhiTexture::Flags flags) = 0; - virtual QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, + virtual QRhiSampler *createSampler(QRhiSampler::Filter magFilter, + QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, - QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) = 0; + QRhiSampler:: AddressMode u, + QRhiSampler::AddressMode v, + QRhiSampler::AddressMode w) = 0; virtual QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags) = 0; diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp index 445d162595..75b90b6995 100644 --- a/src/gui/rhi/qrhid3d11.cpp +++ b/src/gui/rhi/qrhid3d11.cpp @@ -527,9 +527,9 @@ QRhiTexture *QRhiD3D11::createTexture(QRhiTexture::Format format, const QSize &p QRhiSampler *QRhiD3D11::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, - QRhiSampler::AddressMode u, QRhiSampler::AddressMode v) + QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w) { - return new QD3D11Sampler(this, magFilter, minFilter, mipmapMode, u, v); + return new QD3D11Sampler(this, magFilter, minFilter, mipmapMode, u, v, w); } QRhiTextureRenderTarget *QRhiD3D11::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, @@ -2768,8 +2768,8 @@ ID3D11UnorderedAccessView *QD3D11Texture::unorderedAccessViewForLevel(int level) } QD3D11Sampler::QD3D11Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, - AddressMode u, AddressMode v) - : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v) + AddressMode u, AddressMode v, AddressMode w) + : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v, w) { } @@ -3467,6 +3467,9 @@ bool QD3D11GraphicsPipeline::build() rastDesc.FillMode = D3D11_FILL_SOLID; rastDesc.CullMode = toD3DCullMode(m_cullMode); rastDesc.FrontCounterClockwise = m_frontFace == CCW; + rastDesc.DepthBias = m_depthBias; + rastDesc.SlopeScaledDepthBias = m_slopeScaledDepthBias; + rastDesc.DepthClipEnable = true; rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor); rastDesc.MultisampleEnable = rhiD->effectiveSampleCount(m_sampleCount).Count > 1; HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState); diff --git a/src/gui/rhi/qrhid3d11_p_p.h b/src/gui/rhi/qrhid3d11_p_p.h index 9ddd2aa797..c3a4021241 100644 --- a/src/gui/rhi/qrhid3d11_p_p.h +++ b/src/gui/rhi/qrhid3d11_p_p.h @@ -120,7 +120,7 @@ struct QD3D11Texture : public QRhiTexture struct QD3D11Sampler : public QRhiSampler { QD3D11Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, - AddressMode u, AddressMode v); + AddressMode u, AddressMode v, AddressMode w); ~QD3D11Sampler(); void release() override; bool build() override; @@ -559,9 +559,12 @@ public: const QSize &pixelSize, int sampleCount, QRhiTexture::Flags flags) override; - QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, + QRhiSampler *createSampler(QRhiSampler::Filter magFilter, + QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, - QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override; + QRhiSampler:: AddressMode u, + QRhiSampler::AddressMode v, + QRhiSampler::AddressMode w) override; QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags) override; diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index ec5e531e14..62f808ce81 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -838,9 +838,9 @@ QRhiTexture *QRhiGles2::createTexture(QRhiTexture::Format format, const QSize &p QRhiSampler *QRhiGles2::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, - QRhiSampler::AddressMode u, QRhiSampler::AddressMode v) + QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w) { - return new QGles2Sampler(this, magFilter, minFilter, mipmapMode, u, v); + return new QGles2Sampler(this, magFilter, minFilter, mipmapMode, u, v, w); } QRhiTextureRenderTarget *QRhiGles2::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, @@ -2386,7 +2386,14 @@ void QRhiGles2::executeBindGraphicsPipeline(QRhiGraphicsPipeline *ps) f->glDisable(GL_STENCIL_TEST); } - if (psD->topology() == QRhiGraphicsPipeline::Lines || psD->topology() == QRhiGraphicsPipeline::LineStrip) + if (psD->m_depthBias != 0 || !qFuzzyIsNull(psD->m_slopeScaledDepthBias)) { + f->glPolygonOffset(psD->m_slopeScaledDepthBias, psD->m_depthBias); + f->glEnable(GL_POLYGON_OFFSET_FILL); + } else { + f->glDisable(GL_POLYGON_OFFSET_FILL); + } + + if (psD->m_topology == QRhiGraphicsPipeline::Lines || psD->m_topology == QRhiGraphicsPipeline::LineStrip) f->glLineWidth(psD->m_lineWidth); f->glUseProgram(psD->program); @@ -3626,8 +3633,8 @@ QRhiTexture::NativeTexture QGles2Texture::nativeTexture() } QGles2Sampler::QGles2Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, - AddressMode u, AddressMode v) - : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v) + AddressMode u, AddressMode v, AddressMode w) + : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v, w) { } diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h index 679f806004..00caf40118 100644 --- a/src/gui/rhi/qrhigles2_p_p.h +++ b/src/gui/rhi/qrhigles2_p_p.h @@ -170,7 +170,7 @@ struct QGles2Texture : public QRhiTexture struct QGles2Sampler : public QRhiSampler { QGles2Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, - AddressMode u, AddressMode v); + AddressMode u, AddressMode v, AddressMode w); ~QGles2Sampler(); void release() override; bool build() override; @@ -613,9 +613,12 @@ public: const QSize &pixelSize, int sampleCount, QRhiTexture::Flags flags) override; - QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, + QRhiSampler *createSampler(QRhiSampler::Filter magFilter, + QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, - QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override; + QRhiSampler:: AddressMode u, + QRhiSampler::AddressMode v, + QRhiSampler::AddressMode w) override; QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags) override; diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm index 98cbd416b5..9e8f1ac096 100644 --- a/src/gui/rhi/qrhimetal.mm +++ b/src/gui/rhi/qrhimetal.mm @@ -298,6 +298,8 @@ struct QMetalGraphicsPipelineData MTLPrimitiveType primitiveType; MTLWinding winding; MTLCullMode cullMode; + float depthBias; + float slopeScaledDepthBias; QMetalShader vs; QMetalShader fs; }; @@ -626,9 +628,9 @@ QRhiTexture *QRhiMetal::createTexture(QRhiTexture::Format format, const QSize &p QRhiSampler *QRhiMetal::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, - QRhiSampler::AddressMode u, QRhiSampler::AddressMode v) + QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w) { - return new QMetalSampler(this, magFilter, minFilter, mipmapMode, u, v); + return new QMetalSampler(this, magFilter, minFilter, mipmapMode, u, v, w); } QRhiTextureRenderTarget *QRhiMetal::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, @@ -684,11 +686,27 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD bool offsetOnlyChange, const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[SUPPORTED_STAGES]) { - struct { - QRhiBatchedBindings<id<MTLBuffer> > buffers; - QRhiBatchedBindings<NSUInteger> bufferOffsets; - QRhiBatchedBindings<id<MTLTexture> > textures; - QRhiBatchedBindings<id<MTLSamplerState> > samplers; + struct Stage { + struct Buffer { + int nativeBinding; + id<MTLBuffer> mtlbuf; + uint offset; + }; + struct Texture { + int nativeBinding; + id<MTLTexture> mtltex; + }; + struct Sampler { + int nativeBinding; + id<MTLSamplerState> mtlsampler; + }; + QVarLengthArray<Buffer, 8> buffers; + QVarLengthArray<Texture, 8> textures; + QVarLengthArray<Sampler, 8> samplers; + QRhiBatchedBindings<id<MTLBuffer> > bufferBatches; + QRhiBatchedBindings<NSUInteger> bufferOffsetBatches; + QRhiBatchedBindings<id<MTLTexture> > textureBatches; + QRhiBatchedBindings<id<MTLSamplerState> > samplerBatches; } res[SUPPORTED_STAGES]; enum { VERTEX = 0, FRAGMENT = 1, COMPUTE = 2 }; @@ -709,24 +727,18 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD } if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) { const int nativeBinding = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Buffer); - if (nativeBinding >= 0) { - res[VERTEX].buffers.feed(nativeBinding, mtlbuf); - res[VERTEX].bufferOffsets.feed(b->binding, offset); - } + if (nativeBinding >= 0) + res[VERTEX].buffers.append({ nativeBinding, mtlbuf, offset }); } if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) { const int nativeBinding = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Buffer); - if (nativeBinding >= 0) { - res[FRAGMENT].buffers.feed(nativeBinding, mtlbuf); - res[FRAGMENT].bufferOffsets.feed(b->binding, offset); - } + if (nativeBinding >= 0) + res[FRAGMENT].buffers.append({ nativeBinding, mtlbuf, offset }); } if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) { const int nativeBinding = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Buffer); - if (nativeBinding >= 0) { - res[COMPUTE].buffers.feed(nativeBinding, mtlbuf); - res[COMPUTE].bufferOffsets.feed(b->binding, offset); - } + if (nativeBinding >= 0) + res[COMPUTE].buffers.append({ nativeBinding, mtlbuf, offset }); } } break; @@ -738,24 +750,24 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD const int nativeBindingTexture = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Texture); const int nativeBindingSampler = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Sampler); if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) { - res[VERTEX].textures.feed(nativeBindingTexture, texD->d->tex); - res[VERTEX].samplers.feed(nativeBindingSampler, samplerD->d->samplerState); + res[VERTEX].textures.append({ nativeBindingTexture, texD->d->tex }); + res[VERTEX].samplers.append({ nativeBindingSampler, samplerD->d->samplerState }); } } if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) { const int nativeBindingTexture = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Texture); const int nativeBindingSampler = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Sampler); if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) { - res[FRAGMENT].textures.feed(nativeBindingTexture, texD->d->tex); - res[FRAGMENT].samplers.feed(nativeBindingSampler, samplerD->d->samplerState); + res[FRAGMENT].textures.append({ nativeBindingTexture, texD->d->tex }); + res[FRAGMENT].samplers.append({ nativeBindingSampler, samplerD->d->samplerState }); } } if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) { const int nativeBindingTexture = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Texture); const int nativeBindingSampler = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Sampler); if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) { - res[COMPUTE].textures.feed(nativeBindingTexture, texD->d->tex); - res[COMPUTE].samplers.feed(nativeBindingSampler, samplerD->d->samplerState); + res[COMPUTE].textures.append({ nativeBindingTexture, texD->d->tex }); + res[COMPUTE].samplers.append({ nativeBindingSampler, samplerD->d->samplerState }); } } } @@ -769,17 +781,17 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) { const int nativeBinding = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Texture); if (nativeBinding >= 0) - res[VERTEX].textures.feed(nativeBinding, t); + res[VERTEX].textures.append({ nativeBinding, t }); } if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) { const int nativeBinding = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Texture); if (nativeBinding >= 0) - res[FRAGMENT].textures.feed(nativeBinding, t); + res[FRAGMENT].textures.append({ nativeBinding, t }); } if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) { const int nativeBinding = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Texture); if (nativeBinding >= 0) - res[COMPUTE].textures.feed(nativeBinding, t); + res[COMPUTE].textures.append({ nativeBinding, t }); } } break; @@ -792,24 +804,18 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD uint offset = uint(b->u.sbuf.offset); if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) { const int nativeBinding = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Buffer); - if (nativeBinding >= 0) { - res[VERTEX].buffers.feed(nativeBinding, mtlbuf); - res[VERTEX].bufferOffsets.feed(b->binding, offset); - } + if (nativeBinding >= 0) + res[VERTEX].buffers.append({ nativeBinding, mtlbuf, offset }); } if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) { const int nativeBinding = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Buffer); - if (nativeBinding >= 0) { - res[FRAGMENT].buffers.feed(nativeBinding, mtlbuf); - res[FRAGMENT].bufferOffsets.feed(b->binding, offset); - } + if (nativeBinding >= 0) + res[FRAGMENT].buffers.append({ nativeBinding, mtlbuf, offset }); } if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) { const int nativeBinding = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Buffer); - if (nativeBinding >= 0) { - res[COMPUTE].buffers.feed(nativeBinding, mtlbuf); - res[COMPUTE].bufferOffsets.feed(b->binding, offset); - } + if (nativeBinding >= 0) + res[COMPUTE].buffers.append({ nativeBinding, mtlbuf, offset }); } } break; @@ -825,12 +831,26 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD if (cbD->recordingPass != QMetalCommandBuffer::ComputePass && stage == COMPUTE) continue; - res[stage].buffers.finish(); - res[stage].bufferOffsets.finish(); + // QRhiBatchedBindings works with the native bindings and expects + // sorted input. The pre-sorted QRhiShaderResourceBinding list (based + // on the QRhi (SPIR-V) binding) is not helpful in this regard, so we + // have to sort here every time. + + std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](const Stage::Buffer &a, const Stage::Buffer &b) { + return a.nativeBinding < b.nativeBinding; + }); + + for (const Stage::Buffer &buf : qAsConst(res[stage].buffers)) { + res[stage].bufferBatches.feed(buf.nativeBinding, buf.mtlbuf); + res[stage].bufferOffsetBatches.feed(buf.nativeBinding, buf.offset); + } + + res[stage].bufferBatches.finish(); + res[stage].bufferOffsetBatches.finish(); - for (int i = 0, ie = res[stage].buffers.batches.count(); i != ie; ++i) { - const auto &bufferBatch(res[stage].buffers.batches[i]); - const auto &offsetBatch(res[stage].bufferOffsets.batches[i]); + for (int i = 0, ie = res[stage].bufferBatches.batches.count(); i != ie; ++i) { + const auto &bufferBatch(res[stage].bufferBatches.batches[i]); + const auto &offsetBatch(res[stage].bufferOffsetBatches.batches[i]); switch (stage) { case VERTEX: [cbD->d->currentRenderPassEncoder setVertexBuffers: bufferBatch.resources.constData() @@ -856,11 +876,25 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD if (offsetOnlyChange) continue; - res[stage].textures.finish(); - res[stage].samplers.finish(); + std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](const Stage::Texture &a, const Stage::Texture &b) { + return a.nativeBinding < b.nativeBinding; + }); - for (int i = 0, ie = res[stage].textures.batches.count(); i != ie; ++i) { - const auto &batch(res[stage].textures.batches[i]); + std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](const Stage::Sampler &a, const Stage::Sampler &b) { + return a.nativeBinding < b.nativeBinding; + }); + + for (const Stage::Texture &t : qAsConst(res[stage].textures)) + res[stage].textureBatches.feed(t.nativeBinding, t.mtltex); + + for (const Stage::Sampler &s : qAsConst(res[stage].samplers)) + res[stage].samplerBatches.feed(s.nativeBinding, s.mtlsampler); + + res[stage].textureBatches.finish(); + res[stage].samplerBatches.finish(); + + for (int i = 0, ie = res[stage].textureBatches.batches.count(); i != ie; ++i) { + const auto &batch(res[stage].textureBatches.batches[i]); switch (stage) { case VERTEX: [cbD->d->currentRenderPassEncoder setVertexTextures: batch.resources.constData() @@ -879,8 +913,8 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD break; } } - for (int i = 0, ie = res[stage].samplers.batches.count(); i != ie; ++i) { - const auto &batch(res[stage].samplers.batches[i]); + for (int i = 0, ie = res[stage].samplerBatches.batches.count(); i != ie; ++i) { + const auto &batch(res[stage].samplerBatches.batches[i]); switch (stage) { case VERTEX: [cbD->d->currentRenderPassEncoder setVertexSamplerStates: batch.resources.constData() @@ -924,6 +958,14 @@ void QRhiMetal::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline [cbD->d->currentRenderPassEncoder setFrontFacingWinding: psD->d->winding]; cbD->currentFrontFaceWinding = int(psD->d->winding); } + if (!qFuzzyCompare(psD->d->depthBias, cbD->currentDepthBiasValues.first) + || !qFuzzyCompare(psD->d->slopeScaledDepthBias, cbD->currentDepthBiasValues.second)) + { + [cbD->d->currentRenderPassEncoder setDepthBias: psD->d->depthBias + slopeScale: psD->d->slopeScaledDepthBias + clamp: 0.0f]; + cbD->currentDepthBiasValues = { psD->d->depthBias, psD->d->slopeScaledDepthBias }; + } } psD->lastActiveFrameSlot = currentFrameSlot; @@ -2548,8 +2590,8 @@ id<MTLTexture> QMetalTextureData::viewForLevel(int level) } QMetalSampler::QMetalSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, - AddressMode u, AddressMode v) - : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v), + AddressMode u, AddressMode v, AddressMode w) + : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v, w), d(new QMetalSamplerData) { } @@ -3422,6 +3464,8 @@ bool QMetalGraphicsPipeline::build() d->primitiveType = toMetalPrimitiveType(m_topology); d->winding = m_frontFace == CCW ? MTLWindingCounterClockwise : MTLWindingClockwise; d->cullMode = toMetalCullMode(m_cullMode); + d->depthBias = float(m_depthBias); + d->slopeScaledDepthBias = m_slopeScaledDepthBias; lastActiveFrameSlot = -1; generation += 1; @@ -3570,6 +3614,7 @@ void QMetalCommandBuffer::resetPerPassCachedState() currentIndexFormat = QRhiCommandBuffer::IndexUInt16; currentCullMode = -1; currentFrontFaceWinding = -1; + currentDepthBiasValues = { 0.0f, 0.0f }; d->currentFirstVertexBinding = -1; d->currentVertexInputsBuffers.clear(); diff --git a/src/gui/rhi/qrhimetal_p_p.h b/src/gui/rhi/qrhimetal_p_p.h index 71d4325b1a..58e93e2cdb 100644 --- a/src/gui/rhi/qrhimetal_p_p.h +++ b/src/gui/rhi/qrhimetal_p_p.h @@ -120,7 +120,7 @@ struct QMetalSamplerData; struct QMetalSampler : public QRhiSampler { QMetalSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, - AddressMode u, AddressMode v); + AddressMode u, AddressMode v, AddressMode w); ~QMetalSampler(); void release() override; bool build() override; @@ -288,6 +288,7 @@ struct QMetalCommandBuffer : public QRhiCommandBuffer QRhiCommandBuffer::IndexFormat currentIndexFormat; int currentCullMode; int currentFrontFaceWinding; + QPair<float, float> currentDepthBiasValues; const QRhiNativeHandles *nativeHandles(); void resetState(); @@ -349,9 +350,12 @@ public: const QSize &pixelSize, int sampleCount, QRhiTexture::Flags flags) override; - QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, + QRhiSampler *createSampler(QRhiSampler::Filter magFilter, + QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, - QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override; + QRhiSampler:: AddressMode u, + QRhiSampler::AddressMode v, + QRhiSampler::AddressMode w) override; QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags) override; diff --git a/src/gui/rhi/qrhinull.cpp b/src/gui/rhi/qrhinull.cpp index ea67f80138..4c59900aa6 100644 --- a/src/gui/rhi/qrhinull.cpp +++ b/src/gui/rhi/qrhinull.cpp @@ -193,9 +193,9 @@ QRhiTexture *QRhiNull::createTexture(QRhiTexture::Format format, const QSize &pi QRhiSampler *QRhiNull::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, - QRhiSampler::AddressMode u, QRhiSampler::AddressMode v) + QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w) { - return new QNullSampler(this, magFilter, minFilter, mipmapMode, u, v); + return new QNullSampler(this, magFilter, minFilter, mipmapMode, u, v, w); } QRhiTextureRenderTarget *QRhiNull::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, @@ -645,8 +645,8 @@ bool QNullTexture::buildFrom(QRhiTexture::NativeTexture src) } QNullSampler::QNullSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, - AddressMode u, AddressMode v) - : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v) + AddressMode u, AddressMode v, AddressMode w) + : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v, w) { } diff --git a/src/gui/rhi/qrhinull_p_p.h b/src/gui/rhi/qrhinull_p_p.h index f541fd90b8..0b3d40f1aa 100644 --- a/src/gui/rhi/qrhinull_p_p.h +++ b/src/gui/rhi/qrhinull_p_p.h @@ -88,7 +88,7 @@ struct QNullTexture : public QRhiTexture struct QNullSampler : public QRhiSampler { QNullSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, - AddressMode u, AddressMode v); + AddressMode u, AddressMode v, AddressMode w); ~QNullSampler(); void release() override; bool build() override; @@ -212,9 +212,12 @@ public: const QSize &pixelSize, int sampleCount, QRhiTexture::Flags flags) override; - QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, + QRhiSampler *createSampler(QRhiSampler::Filter magFilter, + QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, - QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override; + QRhiSampler:: AddressMode u, + QRhiSampler::AddressMode v, + QRhiSampler::AddressMode w) override; QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags) override; diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index e7faa0cadd..84ca835392 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -2462,9 +2462,10 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i { QVkShaderResourceBindings *srbD = QRHI_RES(QVkShaderResourceBindings, srb); - QVarLengthArray<VkDescriptorBufferInfo, 4> bufferInfos; - QVarLengthArray<VkDescriptorImageInfo, 4> imageInfos; - QVarLengthArray<VkWriteDescriptorSet, 8> writeInfos; + QVarLengthArray<VkDescriptorBufferInfo, 8> bufferInfos; + QVarLengthArray<VkDescriptorImageInfo, 8> imageInfos; + QVarLengthArray<VkWriteDescriptorSet, 12> writeInfos; + QVarLengthArray<QPair<int, int>, 12> infoIndices; const bool updateAll = descSetIdx < 0; int frameSlot = updateAll ? 0 : descSetIdx; @@ -2481,6 +2482,9 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i writeInfo.dstBinding = uint32_t(b->binding); writeInfo.descriptorCount = 1; + int bufferInfoIndex = -1; + int imageInfoIndex = -1; + switch (b->type) { case QRhiShaderResourceBinding::UniformBuffer: { @@ -2496,8 +2500,8 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i bufInfo.range = VkDeviceSize(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size); // be nice and assert when we know the vulkan device would die a horrible death due to non-aligned reads Q_ASSERT(aligned(bufInfo.offset, ubufAlign) == bufInfo.offset); + bufferInfoIndex = bufferInfos.count(); bufferInfos.append(bufInfo); - writeInfo.pBufferInfo = &bufferInfos.last(); } break; case QRhiShaderResourceBinding::SampledTexture: @@ -2513,8 +2517,8 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i imageInfo.sampler = samplerD->sampler; imageInfo.imageView = texD->imageView; imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + imageInfoIndex = imageInfos.count(); imageInfos.append(imageInfo); - writeInfo.pImageInfo = &imageInfos.last(); } break; case QRhiShaderResourceBinding::ImageLoad: @@ -2531,8 +2535,8 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i imageInfo.sampler = VK_NULL_HANDLE; imageInfo.imageView = view; imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + imageInfoIndex = imageInfos.count(); imageInfos.append(imageInfo); - writeInfo.pImageInfo = &imageInfos.last(); } } break; @@ -2548,8 +2552,8 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i bufInfo.buffer = bufD->m_type == QRhiBuffer::Dynamic ? bufD->buffers[frameSlot] : bufD->buffers[0]; bufInfo.offset = VkDeviceSize(b->u.ubuf.offset); bufInfo.range = VkDeviceSize(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size); + bufferInfoIndex = bufferInfos.count(); bufferInfos.append(bufInfo); - writeInfo.pBufferInfo = &bufferInfos.last(); } break; default: @@ -2557,10 +2561,20 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i } writeInfos.append(writeInfo); + infoIndices.append({ bufferInfoIndex, imageInfoIndex }); } ++frameSlot; } + for (int i = 0, writeInfoCount = writeInfos.count(); i < writeInfoCount; ++i) { + const int bufferInfoIndex = infoIndices[i].first; + const int imageInfoIndex = infoIndices[i].second; + if (bufferInfoIndex >= 0) + writeInfos[i].pBufferInfo = &bufferInfos[bufferInfoIndex]; + else if (imageInfoIndex >= 0) + writeInfos[i].pImageInfo = &imageInfos[imageInfoIndex]; + } + df->vkUpdateDescriptorSets(dev, uint32_t(writeInfos.count()), writeInfos.constData(), 0, nullptr); } @@ -4046,9 +4060,9 @@ QRhiTexture *QRhiVulkan::createTexture(QRhiTexture::Format format, const QSize & QRhiSampler *QRhiVulkan::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, - QRhiSampler::AddressMode u, QRhiSampler::AddressMode v) + QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w) { - return new QVkSampler(this, magFilter, minFilter, mipmapMode, u, v); + return new QVkSampler(this, magFilter, minFilter, mipmapMode, u, v, w); } QRhiTextureRenderTarget *QRhiVulkan::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, @@ -5543,8 +5557,8 @@ VkImageView QVkTexture::imageViewForLevel(int level) } QVkSampler::QVkSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, - AddressMode u, AddressMode v) - : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v) + AddressMode u, AddressMode v, AddressMode w) + : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v, w) { } @@ -6208,6 +6222,11 @@ bool QVkGraphicsPipeline::build() rastInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; rastInfo.cullMode = toVkCullMode(m_cullMode); rastInfo.frontFace = toVkFrontFace(m_frontFace); + if (m_depthBias != 0 || !qFuzzyIsNull(m_slopeScaledDepthBias)) { + rastInfo.depthBiasEnable = true; + rastInfo.depthBiasConstantFactor = float(m_depthBias); + rastInfo.depthBiasSlopeFactor = m_slopeScaledDepthBias; + } rastInfo.lineWidth = rhiD->hasWideLines ? m_lineWidth : 1.0f; pipelineInfo.pRasterizationState = &rastInfo; diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h index b0e90dae56..d42b83b882 100644 --- a/src/gui/rhi/qrhivulkan_p_p.h +++ b/src/gui/rhi/qrhivulkan_p_p.h @@ -154,7 +154,7 @@ struct QVkTexture : public QRhiTexture struct QVkSampler : public QRhiSampler { QVkSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode, - AddressMode u, AddressMode v); + AddressMode u, AddressMode v, AddressMode w); ~QVkSampler(); void release() override; bool build() override; @@ -657,9 +657,12 @@ public: const QSize &pixelSize, int sampleCount, QRhiTexture::Flags flags) override; - QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter, + QRhiSampler *createSampler(QRhiSampler::Filter magFilter, + QRhiSampler::Filter minFilter, QRhiSampler::Filter mipmapMode, - QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override; + QRhiSampler:: AddressMode u, + QRhiSampler::AddressMode v, + QRhiSampler::AddressMode w) override; QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc, QRhiTextureRenderTarget::Flags flags) override; |