From d4269c274899495c6006c4e63c84828de61e4cb9 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Sat, 16 Mar 2019 16:30:43 +0100 Subject: [PATCH] Add MRT example --- examples/rhi/mrt/buildshaders.sh | 2 + examples/rhi/mrt/mrt.cpp | 245 ++++++++++++++++++ examples/rhi/mrt/mrt.frag | 22 ++ examples/rhi/mrt/mrt.frag.qsb | Bin 0 -> 1613 bytes examples/rhi/mrt/mrt.pro | 11 + examples/rhi/mrt/mrt.qrc | 8 + examples/rhi/mrt/mrt.vert | 19 ++ examples/rhi/mrt/mrt.vert.qsb | Bin 0 -> 1465 bytes examples/rhi/rhi.pro | 3 +- .../triquadcube/triangleoncuberenderer.cpp | 2 +- examples/rhi/triquadcube/triquadcube.cpp | 6 +- src/rhi/qrhi.cpp | 12 +- src/rhi/qrhi.h | 7 +- src/rhi/qrhi_p.h | 2 +- src/rhi/qrhid3d11.cpp | 4 +- src/rhi/qrhid3d11_p.h | 2 +- src/rhi/qrhigles2.cpp | 16 +- src/rhi/qrhigles2_p.h | 4 +- src/rhi/qrhimetal.mm | 4 +- src/rhi/qrhimetal_p.h | 2 +- src/rhi/qrhinull.cpp | 4 +- src/rhi/qrhinull_p.h | 2 +- src/rhi/qrhivulkan.cpp | 4 +- src/rhi/qrhivulkan_p.h | 2 +- 24 files changed, 361 insertions(+), 22 deletions(-) create mode 100755 examples/rhi/mrt/buildshaders.sh create mode 100644 examples/rhi/mrt/mrt.cpp create mode 100644 examples/rhi/mrt/mrt.frag create mode 100644 examples/rhi/mrt/mrt.frag.qsb create mode 100644 examples/rhi/mrt/mrt.pro create mode 100644 examples/rhi/mrt/mrt.qrc create mode 100644 examples/rhi/mrt/mrt.vert create mode 100644 examples/rhi/mrt/mrt.vert.qsb diff --git a/examples/rhi/mrt/buildshaders.sh b/examples/rhi/mrt/buildshaders.sh new file mode 100755 index 0000000..d7a3d65 --- /dev/null +++ b/examples/rhi/mrt/buildshaders.sh @@ -0,0 +1,2 @@ +qsb --glsl "100 es,120" --hlsl 50 --msl 12 mrt.vert -o mrt.vert.qsb +qsb --glsl "100 es,120" --hlsl 50 --msl 12 mrt.frag -o mrt.frag.qsb diff --git a/examples/rhi/mrt/mrt.cpp b/examples/rhi/mrt/mrt.cpp new file mode 100644 index 0000000..6ce784f --- /dev/null +++ b/examples/rhi/mrt/mrt.cpp @@ -0,0 +1,245 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "../shared/examplefw.h" + +static float quadVertexData[] = +{ // Y up, CCW + -0.5f, 0.5f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.0f, 1.0f, + 0.5f, -0.5f, 1.0f, 1.0f, + 0.5f, 0.5f, 1.0f, 0.0f +}; + +static quint16 quadIndexData[] = +{ + 0, 1, 2, 0, 2, 3 +}; + +static float triangleData[] = +{ // Y up, CCW + 0.0f, 0.5f, 1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, +}; + +struct { + QVector releasePool; + QRhiBuffer *vbuf = nullptr; + QRhiBuffer *ibuf = nullptr; + QRhiBuffer *ubuf = nullptr; + QRhiTextureRenderTarget *rt = nullptr; + QRhiRenderPassDescriptor *rtRp = nullptr; + QRhiTexture *tex = nullptr; + QRhiSampler *sampler = nullptr; + QRhiShaderResourceBindings *srb = nullptr; + QRhiGraphicsPipeline *ps = nullptr; + QRhiResourceUpdateBatch *initialUpdates = nullptr; + QMatrix4x4 winProj; + + QRhiBuffer *triUbuf = nullptr; + QRhiShaderResourceBindings *triSrb = nullptr; + QRhiGraphicsPipeline *triPs = nullptr; + float triRot = 0; + QMatrix4x4 triBaseMvp; +} d; + +void Window::customInit() +{ + qDebug("Max color attachments: %d", m_r->resourceLimit(QRhi::MaxColorAttachments)); + if (m_r->resourceLimit(QRhi::MaxColorAttachments) < 4) + qWarning("MRT is not supported"); + + d.vbuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(quadVertexData) + sizeof(triangleData)); + d.vbuf->build(); + d.releasePool << d.vbuf; + + d.ibuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::IndexBuffer, sizeof(quadIndexData)); + d.ibuf->build(); + d.releasePool << d.ibuf; + + d.ubuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68); + d.ubuf->build(); + d.releasePool << d.ubuf; + + d.tex = m_r->newTexture(QRhiTexture::RGBA8, QSize(512, 512), 1, QRhiTexture::RenderTarget); + d.releasePool << d.tex; + d.tex->build(); + + d.rt = m_r->newTextureRenderTarget({ d.tex }); + d.releasePool << d.rt; + d.rtRp = d.rt->newCompatibleRenderPassDescriptor(); + d.releasePool << d.rtRp; + d.rt->setRenderPassDescriptor(d.rtRp); + d.rt->build(); + + d.sampler = m_r->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None, + QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge); + d.releasePool << d.sampler; + d.sampler->build(); + + d.srb = m_r->newShaderResourceBindings(); + d.releasePool << d.srb; + d.srb->setBindings({ + QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.ubuf), + QRhiShaderResourceBinding::sampledTexture(1, QRhiShaderResourceBinding::FragmentStage, d.tex, d.sampler) + }); + d.srb->build(); + + d.ps = m_r->newGraphicsPipeline(); + d.releasePool << d.ps; + d.ps->setShaderStages({ + { QRhiGraphicsShaderStage::Vertex, getShader(QLatin1String(":/texture.vert.qsb")) }, + { QRhiGraphicsShaderStage::Fragment, getShader(QLatin1String(":/texture.frag.qsb")) } + }); + QRhiVertexInputLayout inputLayout; + inputLayout.setBindings({ + { 4 * sizeof(float) } + }); + inputLayout.setAttributes({ + { 0, 0, QRhiVertexInputAttribute::Float2, 0 }, + { 0, 1, QRhiVertexInputAttribute::Float2, 2 * sizeof(float) } + }); + d.ps->setVertexInputLayout(inputLayout); + d.ps->setShaderResourceBindings(d.srb); + d.ps->setRenderPassDescriptor(m_rp); + d.ps->build(); + + d.initialUpdates = m_r->nextResourceUpdateBatch(); + d.initialUpdates->uploadStaticBuffer(d.vbuf, 0, sizeof(quadVertexData), quadVertexData); + d.initialUpdates->uploadStaticBuffer(d.vbuf, sizeof(quadVertexData), sizeof(triangleData), triangleData); + d.initialUpdates->uploadStaticBuffer(d.ibuf, quadIndexData); + + qint32 flip = m_r->isYUpInFramebuffer() ? 1 : 0; + d.initialUpdates->updateDynamicBuffer(d.ubuf, 64, 4, &flip); + + // triangle + d.triUbuf = m_r->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 68); + d.releasePool << d.triUbuf; + d.triUbuf->build(); + + d.triSrb = m_r->newShaderResourceBindings(); + d.releasePool << d.triSrb; + d.triSrb->setBindings({ + QRhiShaderResourceBinding::uniformBuffer(0, QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage, d.triUbuf) + }); + d.triSrb->build(); + + d.triPs = m_r->newGraphicsPipeline(); + d.releasePool << d.triPs; + d.triPs->setShaderStages({ + { QRhiGraphicsShaderStage::Vertex, getShader(QLatin1String(":/mrt.vert.qsb")) }, + { QRhiGraphicsShaderStage::Fragment, getShader(QLatin1String(":/mrt.frag.qsb")) } + }); + inputLayout.setBindings({ + { 5 * sizeof(float) } + }); + inputLayout.setAttributes({ + { 0, 0, QRhiVertexInputAttribute::Float2, 0 }, + { 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) } + }); + d.triPs->setVertexInputLayout(inputLayout); + d.triPs->setShaderResourceBindings(d.triSrb); + d.triPs->setRenderPassDescriptor(d.rtRp); + d.triPs->build(); + + d.triBaseMvp = m_r->clipSpaceCorrMatrix(); + d.triBaseMvp.perspective(45.0f, d.rt->sizeInPixels().width() / float(d.rt->sizeInPixels().height()), 0.01f, 1000.0f); + d.triBaseMvp.translate(0, 0, -2); + float opacity = 1.0f; + d.initialUpdates->updateDynamicBuffer(d.triUbuf, 64, 4, &opacity); +} + +void Window::customRelease() +{ + for (QRhiResource *r : d.releasePool) + r->releaseAndDestroy(); + d.releasePool.clear(); +} + +void Window::customRender() +{ + QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer(); + QRhiResourceUpdateBatch *u = m_r->nextResourceUpdateBatch(); + if (d.initialUpdates) { + u->merge(d.initialUpdates); + d.initialUpdates->release(); + d.initialUpdates = nullptr; + } + + if (d.winProj != m_proj) { + d.winProj = m_proj; + QMatrix4x4 mvp = m_proj; + mvp.scale(2.5f); + u->updateDynamicBuffer(d.ubuf, 0, 64, mvp.constData()); + } + + QMatrix4x4 triMvp = d.triBaseMvp; + triMvp.rotate(d.triRot, 0, 1, 0); + d.triRot += 1; + u->updateDynamicBuffer(d.triUbuf, 0, 64, triMvp.constData()); + + cb->beginPass(d.rt, { 0.5f, 0.2f, 0, 1 }, { 1, 0 }, u); + cb->setGraphicsPipeline(d.triPs); + cb->setViewport({ 0, 0, float(d.rt->sizeInPixels().width()), float(d.rt->sizeInPixels().height()) }); + cb->setShaderResources(); + cb->setVertexInput(0, { { d.vbuf, sizeof(quadVertexData) } }); + cb->draw(3); + cb->endPass(); + + const QSize outputSizeInPixels = m_sc->currentPixelSize(); + cb->beginPass(m_sc->currentFrameRenderTarget(), { 0.4f, 0.7f, 0.0f, 1.0f }, { 1.0f, 0 }); + cb->setGraphicsPipeline(d.ps); + cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) }); + cb->setShaderResources(); + cb->setVertexInput(0, { { d.vbuf, 0 } }, d.ibuf, 0, QRhiCommandBuffer::IndexUInt16); + cb->drawIndexed(6); + cb->endPass(); +} diff --git a/examples/rhi/mrt/mrt.frag b/examples/rhi/mrt/mrt.frag new file mode 100644 index 0000000..96c3eb8 --- /dev/null +++ b/examples/rhi/mrt/mrt.frag @@ -0,0 +1,22 @@ +#version 440 + +layout(location = 0) in vec3 v_color; + +layout(location = 0) out vec4 c0; +layout(location = 1) out vec4 c1; +layout(location = 2) out vec4 c2; +layout(location = 3) out vec4 c3; + +layout(std140, binding = 0) uniform buf { + mat4 mvp; + float opacity; +} ubuf; + +void main() +{ + vec4 c = vec4(v_color * ubuf.opacity, ubuf.opacity); + c0 = c; + c1 = c; + c2 = c; + c3 = c; +} diff --git a/examples/rhi/mrt/mrt.frag.qsb b/examples/rhi/mrt/mrt.frag.qsb new file mode 100644 index 0000000000000000000000000000000000000000..6c049a40148a5d548f667713a5d70658064f8808 GIT binary patch literal 1613 zcmV-T2D14801=mXob4A)bJIq2ZO3*Z0s#^z#n332P`jnBY^R-0Oei0rz)Ys3B*QQb z8C8~LM_@}vl0$%UD>FTGdgyRqpvNBj1Nu|?6MF2im(KLP-6v}$o3z~PWUYPQpSyZy zjHMW36O3hkeb~J3Bk)Uxu{=Cq!gCH*j@eFs5cpldrD5&By2k|1I;@|7XOeYY(+F(W zVZ%=$hl(AeXCd#dZn|C9L;MutgU5XfpSzY>XKWhqXJK7{^&FgdaTI0TL4bwR*s?X!c?s4si|Z_8W4fw^{CHibV4Y9s`g(s|wYSmr zWPe@tf769|%>v^2F?h~Hjz4GYAR9P#+x2=^K<@*e{hSgtehJSXQb=bkNQpe>S<`k} zw$q8y%w9vDr&tq(zeGnetT|`{{>2pX_pDyi^00n?iY8-!!1@-}0qUcZY4ovY1fIRO z0becf{k0TVhV^#)z;|>K`_OH-eJcoUpX4?5?I*xjn3iJ)eH6P&^~GMnzWIiszoKso z8M!~*zG2$IW6~Sidc`CgQr~7-yXzXku!l6Mce6*p-!l3xISZdxlE1G%VoYIv;0??G z6F0#IJaO_lxB$A=Vckm!y-52GbC}}lvXs*4$U^#Z(RR%4pk=8SdRAa`bw6lz?dC-# z!uxiw^)Y@`b}lN)z=wLOm;)c;w^T0GP!!>r3O*@M6%{@_+@-xG73$H5Fe;_3p*)ME zdWP+2Ivn1ZtZHiN))v16N?Lh)yAh*RhqUSltv009MridRt(DeH0DeCZ$Esv% zWx0zu6UCKaTq=vwKvm)1GZSTO#L(DdBbe$4rZ$49M_seAe)IMn{i^5szJ3$md*j<@ zS>3#L_v)=%w^y}T)5+qu`0H!r5G<=3cl1re>sW!7JOmQ0nmhy&t(H6l60I)$*>&xf ziv6r(IZNe)8&SK(drgn^njY^pxzFStllv>|E$F4uT<}v+8cDGl9w^v{j)rcn$i&L9 z>^znzI)NBtPzZ}bLNLh~Iyu@n3XiWkj>4m@jid0`>#>6sciz4-A%pa8IN>v1bu$~9u92JQu>}{+MI94?(FnMT^l24 z+X=>9?D($S_fn?;fggJ83G6MydyMZ5oZX_6C|WMoZ8(JRUc*i4EpD|=SN{U4yJ`f+ zmbM*rmyEBz0bhFqzP>%|%tR6PqDwCIdsKuP6v1w{tTq88!18prdEYVvf1HK!oTCQ*uX(cOj1C@sCce+4 zi+OB?JPg?H6ZQza|5AKZ&GF~;wT-n3%u|)6Pw?f)4#9xOsDWl+n46$^EVO}h8BE!1 z0ag*#BCNw8gFHCWXW$Rtu)pER2v}J*3p5;4O(tllEBpb4v>AYLUd#b)hWy1rIS14k z@+ll>Q645z8Zd=!^vl%59{n?`Vvl~BHL*v3@u%5!vi~00xgpuiayUDLi$k6Wm*;Uu zxD@eS!kkhpX(sHTpJzxegcl@uUh)Is1%guq7YPpaEfS2Cngwi{>&tK$_s3xezhL;! zgm-`+ea%rFRrsDH|MNswh@K((0kVzw2Eo&WI|1+^lAYjwh`b#l9Vma8{FotmgpUyJ z7{Eu#H`Mnb!LtOT{2cLy`odWAqz~bF!iDfc0xl-tMS?$tdZo#CM!3HKlO + + mrt.vert.qsb + mrt.frag.qsb + ../shared/texture.vert.qsb + ../shared/texture.frag.qsb + + diff --git a/examples/rhi/mrt/mrt.vert b/examples/rhi/mrt/mrt.vert new file mode 100644 index 0000000..43af543 --- /dev/null +++ b/examples/rhi/mrt/mrt.vert @@ -0,0 +1,19 @@ +#version 440 + +layout(location = 0) in vec4 position; +layout(location = 1) in vec3 color; + +layout(location = 0) out vec3 v_color; + +layout(std140, binding = 0) uniform buf { + mat4 mvp; + float opacity; +} ubuf; + +out gl_PerVertex { vec4 gl_Position; }; + +void main() +{ + v_color = color; + gl_Position = ubuf.mvp * position; +} diff --git a/examples/rhi/mrt/mrt.vert.qsb b/examples/rhi/mrt/mrt.vert.qsb new file mode 100644 index 0000000000000000000000000000000000000000..66421b1959e5c6bd0bc15c60dc12641917fc55c3 GIT binary patch literal 1465 zcmV;q1xES+01r)goaI(aZzDwzZriaPPu_{MS(0qFAqd&97$-3Zeef+On_n&{4u@M$J zcEj~r_rUg3pM9TD{=b9gR|(u_EJ!H-Syr{3y6qgt?%5Ui&#@{he}W)VtQt0e|7{NC zTcTAJ9>(<>)#(>lU&0!q7-y4+t7QeAeSQG{>VWr3t5u4%&e|Y1IfylP8x3Csk?+|- zl=JN`KyGeWj~DDwzBw#-W!tbG!TO9LUX|0il%6}cZPo1Hg6u}VUNX&xmeVwAG+is` z)*h@U31t`ee!@7^*O8`_ z4#ysn*+tu_HN(2#>n#yjP16tRO}n~j#C+dw)!)N^rISs=2z{t0#~k<&zu;19%`g-) z4w#JR28W*vw{l+LP>;2k!zpcR#$~M4vTUbpLR0IyE1bHMKYkqg!Ye?}IOXEek!G#J zkDKNmeMBG^eNQNK&A#n)LF4UM&kCTGs$n1sJq}iQ1R)k#Dn{ndgcpeO7`}QdMDDna zw*A057C;>x-2r0`kdDmLTO2D00`R{9;i2auA&f2J+ThPG6(*ocQC2pdwMoD zr2P`4pTCWwQMgLl6G7-Xs05)H2DXQEO2^4^+#{*!nnH-6`6_50+kOCmtK|r;=YDRs ztWyBhsXF>L(f2Bcfb)R^s3Cd;D@B!JC?T9+wLaxu>)PscOE0?*GcJAH zA_sd9_Yckcp6mPOL%b>eqE}Y=qmMtmzq`BtpxmcT;@zdL2Gp(Z%CozFr}wws-Q}zN z;806~>_gYCb8JQvYgmZN5_gK$CfzO43Y&!}wmY4o6=hFc2QB-ua4l6lYH@gvd`F(O zExlRWF$7(ryGON%6r&F!rLFEmC8TqDK8UXFxh5N@tJ6x_m(uO%62F)M#KzR{QD>bY zg#Ek-$bEFVR4(^98u7OI+hdWgSoy(WO|Zn4cY!A_-pnz+&Y`6E{kUDtE*s_F_K0?j z#HQ4lp=aPcJ~9$N#2HvF!(Gy-iw57?G4Jl*GyM|_X9BZnImaR9w6a{rFW*=c=Yepf z)<1~KQ|MV}djgbT!f5om5N*q|0wE0u&vdJ&q89l5JoJ~m?%@AWMMixb9sIwhl8ad^ zZWcyKPTUE&9};pP%gE=}&cRLzriN1GeY`x_D2y?TT4GF&PHO6ieB@}D8^?hPy}%#d zIInOJ0!dvKX_Sw~RHRWi8d}qUVHBPisqhZvZH#&u;xpQdrtCEM8Ye!!=i!M{R0izk ziI3xB26polLp0{0?;Aj?u?zLn5`R3xLoNvK0@>OkybEM&8+0OELmiovgr_68&lm6H+D9V0uVq&r4&BX1h$3BrZ8-XVID zVz~+Q6xmX?RgR~~AKIU$81rO*TE?q*xIaVhQ$){_uMv_*dX9Lwzd+b<{{yH^l6*7b z{|+3i?*`>@m~ycRyE&rog2ar(udqy#JYsl__#2eBdGh}?=pcQIWah~Z;<-&ZnysrvFKB{BqN5 literal 0 HcmV?d00001 diff --git a/examples/rhi/rhi.pro b/examples/rhi/rhi.pro index 93926a9..367e5e9 100644 --- a/examples/rhi/rhi.pro +++ b/examples/rhi/rhi.pro @@ -13,7 +13,8 @@ SUBDIRS += \ imguidemo \ triquadcube \ offscreen \ - floattexture + floattexture \ + mrt qtConfig(vulkan) { SUBDIRS += \ diff --git a/examples/rhi/triquadcube/triangleoncuberenderer.cpp b/examples/rhi/triquadcube/triangleoncuberenderer.cpp index 7493088..60bf287 100644 --- a/examples/rhi/triquadcube/triangleoncuberenderer.cpp +++ b/examples/rhi/triquadcube/triangleoncuberenderer.cpp @@ -108,7 +108,7 @@ void TriangleOnCubeRenderer::initResources(QRhiRenderPassDescriptor *rp) if (DEPTH_TEXTURE) { m_offscreenTriangle.setDepthWrite(true); - m_depthTex = m_r->newTexture(QRhiTexture::D32, OFFSCREEN_SIZE, 1, QRhiTexture::RenderTarget); + m_depthTex = m_r->newTexture(QRhiTexture::D32F, OFFSCREEN_SIZE, 1, QRhiTexture::RenderTarget); m_depthTex->build(); } diff --git a/examples/rhi/triquadcube/triquadcube.cpp b/examples/rhi/triquadcube/triquadcube.cpp index f6a742a..d7b5465 100644 --- a/examples/rhi/triquadcube/triquadcube.cpp +++ b/examples/rhi/triquadcube/triquadcube.cpp @@ -166,8 +166,10 @@ void Window::customInit() qDebug("isFeatureSupported(NonDynamicUniformBuffers): %d", m_r->isFeatureSupported(QRhi::NonDynamicUniformBuffers)); qDebug("isFeatureSupported(NonFourAlignedEffectiveIndexBufferOffset): %d", m_r->isFeatureSupported(QRhi::NonFourAlignedEffectiveIndexBufferOffset)); qDebug("isFeatureSupported(NPOTTextureRepeat): %d", m_r->isFeatureSupported(QRhi::NPOTTextureRepeat)); - qDebug("Min 2D texture width/height: %d", m_r->resourceSizeLimit(QRhi::TextureSizeMin)); - qDebug("Max 2D texture width/height: %d", m_r->resourceSizeLimit(QRhi::TextureSizeMax)); + qDebug("isFeatureSupported(RedOrAlpha8IsRed): %d", m_r->isFeatureSupported(QRhi::RedOrAlpha8IsRed)); + qDebug("Min 2D texture width/height: %d", m_r->resourceLimit(QRhi::TextureSizeMin)); + qDebug("Max 2D texture width/height: %d", m_r->resourceLimit(QRhi::TextureSizeMax)); + qDebug("Max color attachment count: %d", m_r->resourceLimit(QRhi::MaxColorAttachments)); } void Window::customRelease() diff --git a/src/rhi/qrhi.cpp b/src/rhi/qrhi.cpp index 897e595..d2f0ff6 100644 --- a/src/rhi/qrhi.cpp +++ b/src/rhi/qrhi.cpp @@ -431,7 +431,7 @@ QT_BEGIN_NAMESPACE */ /*! - \enum QRhi::ResourceSizeLimit + \enum QRhi::ResourceLimit Describes the resource limit to query. \value TextureSizeMin Minimum texture width and height. This is typically @@ -443,6 +443,12 @@ QT_BEGIN_NAMESPACE graphics API and sometimes the platform or implementation as well. Typically the value is in the range 4096 - 16384. Attempting to create textures larger than this is expected to fail. + + \value MaxColorAttachments The maximum number of color attachments for a + QRhiTextureRenderTarget, in case multiple render targets are supported. When + MRT is not supported, the value is 1. Otherwise this is typically 8, but + watch out for the fact that OpenGL only mandates 4 as the minimum, and that + is what some OpenGL ES implementations provide. */ /*! @@ -4126,9 +4132,9 @@ bool QRhi::isFeatureSupported(QRhi::Feature feature) const The values are expected to be queried by the backends upon initialization, meaning calling this function is a light operation. */ -int QRhi::resourceSizeLimit(ResourceSizeLimit limit) const +int QRhi::resourceLimit(ResourceLimit limit) const { - return d->resourceSizeLimit(limit); + return d->resourceLimit(limit); } /*! diff --git a/src/rhi/qrhi.h b/src/rhi/qrhi.h index 3d21055..8af38d2 100644 --- a/src/rhi/qrhi.h +++ b/src/rhi/qrhi.h @@ -1254,9 +1254,10 @@ public: }; Q_DECLARE_FLAGS(EndFrameFlags, EndFrameFlag) - enum ResourceSizeLimit { + enum ResourceLimit { TextureSizeMin = 1, - TextureSizeMax + TextureSizeMax, + MaxColorAttachments }; ~QRhi(); @@ -1319,7 +1320,7 @@ public: bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags = QRhiTexture::Flags()) const; bool isFeatureSupported(QRhi::Feature feature) const; - int resourceSizeLimit(ResourceSizeLimit limit) const; + int resourceLimit(ResourceLimit limit) const; const QRhiNativeHandles *nativeHandles(); diff --git a/src/rhi/qrhi_p.h b/src/rhi/qrhi_p.h index 6589868..0d98813 100644 --- a/src/rhi/qrhi_p.h +++ b/src/rhi/qrhi_p.h @@ -133,7 +133,7 @@ public: virtual QMatrix4x4 clipSpaceCorrMatrix() const = 0; virtual bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const = 0; virtual bool isFeatureSupported(QRhi::Feature feature) const = 0; - virtual int resourceSizeLimit(QRhi::ResourceSizeLimit limit) const = 0; + virtual int resourceLimit(QRhi::ResourceLimit limit) const = 0; virtual const QRhiNativeHandles *nativeHandles() = 0; virtual void sendVMemStatsToProfiler(); diff --git a/src/rhi/qrhid3d11.cpp b/src/rhi/qrhid3d11.cpp index 8dcab6a..1022633 100644 --- a/src/rhi/qrhid3d11.cpp +++ b/src/rhi/qrhid3d11.cpp @@ -365,13 +365,15 @@ bool QRhiD3D11::isFeatureSupported(QRhi::Feature feature) const } } -int QRhiD3D11::resourceSizeLimit(QRhi::ResourceSizeLimit limit) const +int QRhiD3D11::resourceLimit(QRhi::ResourceLimit limit) const { switch (limit) { case QRhi::TextureSizeMin: return 1; case QRhi::TextureSizeMax: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; + case QRhi::MaxColorAttachments: + return 8; default: Q_UNREACHABLE(); return 0; diff --git a/src/rhi/qrhid3d11_p.h b/src/rhi/qrhid3d11_p.h index 2de8db4..3956c0d 100644 --- a/src/rhi/qrhid3d11_p.h +++ b/src/rhi/qrhid3d11_p.h @@ -535,7 +535,7 @@ public: QMatrix4x4 clipSpaceCorrMatrix() const override; bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override; bool isFeatureSupported(QRhi::Feature feature) const override; - int resourceSizeLimit(QRhi::ResourceSizeLimit limit) const override; + int resourceLimit(QRhi::ResourceLimit limit) const override; const QRhiNativeHandles *nativeHandles() override; void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates); diff --git a/src/rhi/qrhigles2.cpp b/src/rhi/qrhigles2.cpp index 891e587..9658b78 100644 --- a/src/rhi/qrhigles2.cpp +++ b/src/rhi/qrhigles2.cpp @@ -196,6 +196,10 @@ QT_BEGIN_NAMESPACE #define GL_FRAMEBUFFER_SRGB 0x8DB9 #endif +#ifndef GL_MAX_DRAW_BUFFERS +#define GL_MAX_DRAW_BUFFERS 0x8824 +#endif + static QSurfaceFormat qrhigles2_effectiveFormat() { QSurfaceFormat fmt = QSurfaceFormat::defaultFormat(); @@ -297,6 +301,8 @@ bool QRhiGles2::create(QRhi::Flags flags) if (vendor && renderer && version) qDebug("OpenGL VENDOR: %s RENDERER: %s VERSION: %s", vendor, renderer, version); + const QSurfaceFormat actualFormat = ctx->format(); + GLint n = 0; f->glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &n); supportedCompressedFormats.resize(n); @@ -305,13 +311,17 @@ bool QRhiGles2::create(QRhi::Flags flags) f->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &caps.maxTextureSize); + if (actualFormat.renderableType() == QSurfaceFormat::OpenGL || actualFormat.version() >= qMakePair(3, 0)) + f->glGetIntegerv(GL_MAX_DRAW_BUFFERS, &caps.maxDrawBuffers); + else + caps.maxDrawBuffers = 1; + caps.msaaRenderBuffer = f->hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample) && f->hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit); caps.npotTexture = f->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures); caps.npotTextureRepeat = f->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat); - const QSurfaceFormat actualFormat = ctx->format(); if (actualFormat.renderableType() == QSurfaceFormat::OpenGLES) caps.fixedIndexPrimitiveRestart = actualFormat.version() >= qMakePair(3, 0); else @@ -532,13 +542,15 @@ bool QRhiGles2::isFeatureSupported(QRhi::Feature feature) const } } -int QRhiGles2::resourceSizeLimit(QRhi::ResourceSizeLimit limit) const +int QRhiGles2::resourceLimit(QRhi::ResourceLimit limit) const { switch (limit) { case QRhi::TextureSizeMin: return 1; case QRhi::TextureSizeMax: return caps.maxTextureSize; + case QRhi::MaxColorAttachments: + return caps.maxDrawBuffers; default: Q_UNREACHABLE(); return 0; diff --git a/src/rhi/qrhigles2_p.h b/src/rhi/qrhigles2_p.h index 178d6a0..f7e1feb 100644 --- a/src/rhi/qrhigles2_p.h +++ b/src/rhi/qrhigles2_p.h @@ -534,7 +534,7 @@ public: QMatrix4x4 clipSpaceCorrMatrix() const override; bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override; bool isFeatureSupported(QRhi::Feature feature) const override; - int resourceSizeLimit(QRhi::ResourceSizeLimit limit) const override; + int resourceLimit(QRhi::ResourceLimit limit) const override; const QRhiNativeHandles *nativeHandles() override; bool ensureContext(QSurface *surface = nullptr) const; @@ -554,6 +554,7 @@ public: struct Caps { Caps() : maxTextureSize(2048), + maxDrawBuffers(4), msaaRenderBuffer(false), npotTexture(true), npotTextureRepeat(true), @@ -567,6 +568,7 @@ public: srgbCapableDefaultFramebuffer(false) { } int maxTextureSize; + int maxDrawBuffers; // Multisample fb and blit are supported (GLES 3.0 or OpenGL 3.x). Not // the same as multisample textures! uint msaaRenderBuffer : 1; diff --git a/src/rhi/qrhimetal.mm b/src/rhi/qrhimetal.mm index a83f7ec..5d25402 100644 --- a/src/rhi/qrhimetal.mm +++ b/src/rhi/qrhimetal.mm @@ -484,13 +484,15 @@ bool QRhiMetal::isFeatureSupported(QRhi::Feature feature) const } } -int QRhiMetal::resourceSizeLimit(QRhi::ResourceSizeLimit limit) const +int QRhiMetal::resourceLimit(QRhi::ResourceLimit limit) const { switch (limit) { case QRhi::TextureSizeMin: return 1; case QRhi::TextureSizeMax: return caps.maxTextureSize; + case QRhi::MaxColorAttachments: + return 8; default: Q_UNREACHABLE(); return 0; diff --git a/src/rhi/qrhimetal_p.h b/src/rhi/qrhimetal_p.h index 87f4dd4..dd1814f 100644 --- a/src/rhi/qrhimetal_p.h +++ b/src/rhi/qrhimetal_p.h @@ -357,7 +357,7 @@ public: QMatrix4x4 clipSpaceCorrMatrix() const override; bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override; bool isFeatureSupported(QRhi::Feature feature) const override; - int resourceSizeLimit(QRhi::ResourceSizeLimit limit) const override; + int resourceLimit(QRhi::ResourceLimit limit) const override; const QRhiNativeHandles *nativeHandles() override; void executeDeferredReleases(bool forced = false); diff --git a/src/rhi/qrhinull.cpp b/src/rhi/qrhinull.cpp index 4d36ba8..0ee2220 100644 --- a/src/rhi/qrhinull.cpp +++ b/src/rhi/qrhinull.cpp @@ -133,13 +133,15 @@ bool QRhiNull::isFeatureSupported(QRhi::Feature feature) const return true; } -int QRhiNull::resourceSizeLimit(QRhi::ResourceSizeLimit limit) const +int QRhiNull::resourceLimit(QRhi::ResourceLimit limit) const { switch (limit) { case QRhi::TextureSizeMin: return 1; case QRhi::TextureSizeMax: return 16384; + case QRhi::MaxColorAttachments: + return 8; default: Q_UNREACHABLE(); return 0; diff --git a/src/rhi/qrhinull_p.h b/src/rhi/qrhinull_p.h index 155ad89..f705b0c 100644 --- a/src/rhi/qrhinull_p.h +++ b/src/rhi/qrhinull_p.h @@ -243,7 +243,7 @@ public: QMatrix4x4 clipSpaceCorrMatrix() const override; bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override; bool isFeatureSupported(QRhi::Feature feature) const override; - int resourceSizeLimit(QRhi::ResourceSizeLimit limit) const override; + int resourceLimit(QRhi::ResourceLimit limit) const override; const QRhiNativeHandles *nativeHandles() override; QRhiNullNativeHandles nativeHandlesStruct; diff --git a/src/rhi/qrhivulkan.cpp b/src/rhi/qrhivulkan.cpp index 08e2317..ce943ba 100644 --- a/src/rhi/qrhivulkan.cpp +++ b/src/rhi/qrhivulkan.cpp @@ -2976,13 +2976,15 @@ bool QRhiVulkan::isFeatureSupported(QRhi::Feature feature) const } } -int QRhiVulkan::resourceSizeLimit(QRhi::ResourceSizeLimit limit) const +int QRhiVulkan::resourceLimit(QRhi::ResourceLimit limit) const { switch (limit) { case QRhi::TextureSizeMin: return 1; case QRhi::TextureSizeMax: return physDevProperties.limits.maxImageDimension2D; + case QRhi::MaxColorAttachments: + return physDevProperties.limits.maxColorAttachments; default: Q_UNREACHABLE(); return 0; diff --git a/src/rhi/qrhivulkan_p.h b/src/rhi/qrhivulkan_p.h index e7fc9b7..c45d502 100644 --- a/src/rhi/qrhivulkan_p.h +++ b/src/rhi/qrhivulkan_p.h @@ -428,7 +428,7 @@ public: QMatrix4x4 clipSpaceCorrMatrix() const override; bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override; bool isFeatureSupported(QRhi::Feature feature) const override; - int resourceSizeLimit(QRhi::ResourceSizeLimit limit) const override; + int resourceLimit(QRhi::ResourceLimit limit) const override; const QRhiNativeHandles *nativeHandles() override; void sendVMemStatsToProfiler() override; -- GitLab