summaryrefslogtreecommitdiffstats
path: root/src/gui/rhi/qrhi.cpp
Commit message (Collapse)AuthorAgeFilesLines
...
* rhi: Make the mip size helpers staticLaszlo Agocs2023-02-201-2/+2
| | | | | Change-Id: Ibe480330290ccddeac0a62b52a8a33c3399cb5bc Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* rhi: Use QHashCombineLaszlo Agocs2023-02-201-17/+50
| | | | | Change-Id: Id83abf97a0e91cdc1624e5523abd6492c5ab7393 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* rhi: Remove QRhiSrb data gettersLaszlo Agocs2023-02-201-8/+8
| | | | | | | | | | | | | | | | This is for internal use, QRhiShaderResourceBinding does not need to have the data() getters. The backends can use any internal means to access this, no need to have the getters in the frontend just for that. Now, Qt Quick 3D has a special case of accessing this, hence keeping the two getters for now, to be removed in a follow up once that repo updates. While we are at it, share and reuse the sorting function. Change-Id: Ia2308af79863c72ca65024ce6c00531d0256a2cb Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* rhi: Add D3D12 supportLaszlo Agocs2023-02-071-1/+44
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | - The optional nice-to-haves DebugMarkers, Timestamps, PipelineCache are not yet implemented (features reported as false, to be implemented later, although buffer/texture resource name setting already works as-is, regardless of DebugMarkers). - Mipmap generation for 3D textures is missing. Won't matter much given that 3D textures are not used in Qt for anything atm. For generating mipmaps for 2D (or 2D array) textures, the MiniEngine compute shader and approach is used. 3D support for the mipmap generator may be added later. 1D textures / arrays are supported except for mipmap generation, and so the OneDimensionalTextureMipmaps feature is reported as false. - Qt Quick and Qt Quick 3D are expected to be fully functional. (unforeseen issues are not impossible, of course) - Uses minimum feature level 11.0 when requesting the device. It is expected to be functional on resource binding tier 1 hardware even, although this has not been verified in practice. - 2 frames in flight with the usual resource buffering (QRhiBuffer::Dynamic is host visible (UPLOAD) and always mapped and slotted, other buffers and textures are device local (DEFAULT). Requests 3 swapchain buffers. Swapchains are mostly like with D3D11 (e.g. FLIP_DISCARD and SCALING_NONE). - The root signature generation is somewhat limited by the SPIR-V binding model and that we need to map every binding point using the nativeResourceBindingMap from the QShader. Thus the root signature is laid out so each stage has its own set of resources, with shader register clashes being prevented by setting the visibility to a given stage. Sampler handling is somewhat suboptimal but we are tied by the binding model and existing API design. It is in a fairly special situation due to the 2048 limit on a shader visible sampler heap, as opposed to 1000000 for SRVs and UAVS, so the approach we use for textures (just stage the CPU SRVs on the (per-frame slot) shader visible heap as they are encountered, effectively treating the heap as a ring buffer) would quickly lead to having to switch heaps many times with scenes with many draw calls and sampledTexture/sampler bindings in the srb. Whereas static samplers, which would be beautiful, are impossible to utilize safely since we do not have that concept (i.e. samplers specified upfront, tied to the graphics/compute pipeline) in the QRhi API, and an srb used at pipeline creation may change its associated resources, such as the QRhiSampler reference, by the time the shader resources are set for the draw call (or another, compatible srb may get used altogether), so specifying the samplers at root signature creation time is impossible. Rather, the current approach is to treat each sampler as a separate root parameter (per stage) having a descriptor table with a single entry. The shader visible sampler heap has exactly one instance of each unique sampler encountered during the lifetime of the QRhi. - Shader-wise no different from D3D11, works with HLSL/DXBC 5.0 (i.e. existing .qsb files with DXBC in them work as-is). But unlike D3D11, this one will try to pick 6.7, 6.6, ..., down to 5.0 from the QShader, in that order. - Uses D3D12MA for suballocating. As a result it can report vmem allocation statistics like the Vulkan backend, and it does more since the DXGI memory usage (incl. implicit resources) is also reported. This is optional technically, so we also have the option of going straight with the heavyweight CreateCommittedResource() instead. That is what we do if the adapter chosen reports it's software-based or when QT_D3D_NO_SUBALLOC=1 is set. - PreferSoftwareRenderer (picking the WARP device) and the env.var. QT_D3D_ADAPTER_INDEX work as with the D3D11 backend. - It is not unexpected that with large scenes that generate lots of draw calls with multiple textures/samplers per call the performance may be slightly below D3D11 (probably mostly due to descriptor management). Similarly, the reported memory usage will be higher, which is partly natural due to creating heaps, descriptor pools, staging areas, etc. upfront. Will need to be evaluated later how these can be tuned. Change-Id: I5a42580bb65f391ebceaf81adc6ae673cceacb74 Reviewed-by: Andy Nichols <andy.nichols@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
* rhi: metal: Add enablers for pre-querying window stuff on the gui threadLaszlo Agocs2023-01-041-0/+43
| | | | | | | | Pick-to: 6.5 Task-number: QTBUG-97518 Change-Id: Ia8fb5128149c9f91ebedfa914d1fe3e3d49774dc Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
* Add support for stereoscopic content in QOpenGLWidgetKristoffer Skau2022-11-281-3/+3
| | | | | | | | | | | | | | | | | Need to add the plumbing necessary to support two textures in QOpenGLWidget and use these in the backing store. The changes required on the RHI level is already done in an earlier patch. Then paintGL() needs to be called twice, once for each buffer. Also add overloads for the other functions of QOopenGLWidget where it makes sense to query for left or right buffer. Then finally create an example. [ChangeLog][Widgets][QOpenGLWidget] Added support for stereoscopic rendering. Fixes: QTBUG-64587 Change-Id: I5a5c53506dcf8a56442097290dceb7eb730d50ce Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
* RHI: Add support for 1D texturesBen Fletcher2022-11-151-5/+46
| | | | | | | Support for 1D textures on Vulkan, OpenGL, Metal, and D3D. Change-Id: Ie74ec103da9cfcbf83fa78588cf8cfc1bd6e104f Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
* Add support for stereoscopic content in QRhi::OpenGLES2Kristoffer Skau2022-11-071-0/+29
| | | | | | | | | | Setting the flag QSurfaceFormat::StereoBuffers does not actually do anything, because we do not utilize the extra buffers provided. We need to expose setting the correct buffers using glDrawBuffers between draw calls. Change-Id: I6a5110405e621030ac3a2886fa83df0cfe928723 Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
* rhi: vk: Switch to cheaper VMA statistics APILaszlo Agocs2022-10-201-3/+0
| | | | | | | | Now that we upgraded to 3.0.1 vmaCalculateStatistics can be replaced with a less-expensive call. Change-Id: Icb444354ce9e091cf69f82aff2e2f828b8302072 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* Long live Q_UNREACHABLE_RETURN()!Marc Mutz2022-10-151-16/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is a combination of Q_UNREACHABLE() with a return statement. ATM, the return statement is unconditionally included. If we notice that some compilers warn about return after __builtin_unreachable(), then we can map Q_UNREACHABLE_RETURN(...) to Q_UNREACHABLE() without having to touch all the code that uses explicit Q_UNREACHABLE() + return. The fact that Boost has BOOST_UNREACHABLE_RETURN() indicates that there are compilers that complain about a lack of return after Q_UNREACHABLE (we know that MSVC, ICC, and GHS are among them), as well as compilers that complained about a return being present (Coverity). Take this opportunity to properly adapt to Coverity, by leaving out the return statement on this compiler. Apply the macro around the code base, using a clang-tidy transformer rule: const std::string unr = "unr", val = "val", ret = "ret"; auto makeUnreachableReturn = cat("Q_UNREACHABLE_RETURN(", ifBound(val, cat(node(val)), cat("")), ")"); auto ignoringSwitchCases = [](auto stmt) { return anyOf(stmt, switchCase(subStmt(stmt))); }; makeRule( stmt(ignoringSwitchCases(stmt(isExpandedFromMacro("Q_UNREACHABLE")).bind(unr)), nextStmt(returnStmt(optionally(hasReturnValue(expr().bind(val)))).bind(ret))), {changeTo(node(unr), cat(makeUnreachableReturn, ";")), // TODO: why is the ; lost w/o this? changeTo(node(ret), cat(""))}, cat("use ", makeUnreachableReturn)) ); where nextStmt() is copied from some upstream clang-tidy check's private implementation and subStmt() is a private matcher that gives access to SwitchCase's SubStmt. A.k.a. qt-use-unreachable-return. There were some false positives, suppressed them with NOLINTNEXTLINE. They're not really false positiives, it's just that Clang sees the world in one way and if conditonal compilation (#if) differs for other compilers, Clang doesn't know better. This is an artifact of matching two consecutive statements. I haven't figured out how to remove the empty line left by the deletion of the return statement, if it, indeed, was on a separate line, so post-processed the patch to remove all the lines matching ^\+ *$ from the diff: git commit -am meep git reset --hard HEAD^ git diff HEAD..HEAD@{1} | sed '/^\+ *$/d' | recountdiff - | patch -p1 [ChangeLog][QtCore][QtAssert] Added Q_UNREACHABLE_RETURN() macro. Change-Id: I9782939f16091c964f25b7826e1c0dbd13a71305 Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* Port from qAsConst() to std::as_const()Marc Mutz2022-10-111-3/+3
| | | | | | | | | | | | | | | | We've been requiring C++17 since Qt 6.0, and our qAsConst use finally starts to bother us (QTBUG-99313), so time to port away from it now. Since qAsConst has exactly the same semantics as std::as_const (down to rvalue treatment, constexpr'ness and noexcept'ness), there's really nothing more to it than a global search-and-replace, with manual unstaging of the actual definition and documentation in dist/, src/corelib/doc/ and src/corelib/global/. Task-number: QTBUG-99313 Change-Id: I4c7114444a325ad4e62d0fcbfd347d2bbfb21541 Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
* rhi: Add a way to query the parent QRhi from a resourceLaszlo Agocs2022-10-051-0/+8
| | | | | | | | | | Quick3D introduces the need to verify the QRhi when only a QRhiTexture (pulled out from a QSGTexture) is available. To enable this, there needs to be a way to retrieve the QRhi from the QRhiTexture. Change-Id: I00777f08b030a7de742169beb0b99ca6282d51a6 Reviewed-by: Christian Strømme <christian.stromme@qt.io>
* Port from container.count()/length() to size()Marc Mutz2022-10-041-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is semantic patch using ClangTidyTransformator: auto QtContainerClass = expr(hasType(namedDecl(hasAnyName(<classes>)))).bind(o) makeRule(cxxMemberCallExpr(on(QtContainerClass), callee(cxxMethodDecl(hasAnyName({"count", "length"), parameterCountIs(0))))), changeTo(cat(access(o, cat("size"), "()"))), cat("use 'size()' instead of 'count()/length()'")) a.k.a qt-port-to-std-compatible-api with config Scope: 'Container'. <classes> are: // sequential: "QByteArray", "QList", "QQueue", "QStack", "QString", "QVarLengthArray", "QVector", // associative: "QHash", "QMultiHash", "QMap", "QMultiMap", "QSet", // Qt has no QMultiSet Change-Id: Ibe8837be96e8d30d1846881ecd65180c1bc459af Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
* rhi: metal: Implement pipeline cache save/loadLaszlo Agocs2022-09-121-0/+10
| | | | | | | | Fixes: QTBUG-106161 Task-number: QTBUG-103802 Change-Id: I51443b72cad0247d3616c075e3dfb7dacea8ca64 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* Apply Q_CONSTINIT where beneficialSona Kurazyan2022-09-011-1/+1
| | | | | | | | | | Applied Q_CONSTINIT to variables with static storage duration, but skipped the POD types with core constant initializers. Task-number: QTBUG-100486 Change-Id: Iaabf824e9cb0f29a405a149912200d4e4b3573c1 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
* rhi: metal: Add support for tessellationLaszlo Agocs2022-09-011-13/+93
| | | | | Change-Id: Ie8d226a6a959aa5e78284ea72505fd26aec1e671 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* rhi: Enhance internal docs about buffer and image load/storeLaszlo Agocs2022-08-161-0/+63
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Comparing the backends revealed that one cannot expect that exposing a storage buffer or a texture to a shader with bufferLoad, imageLoad, bufferStore, imageStore, etc. will always be functional in any graphics and compute pipeline stage. In fact the only place where this is universally supported are compute shaders. In other shaders some backends will not expose the resources at all, e.g. because in D3D11 unordered access views (for a buffer or image used with load/store) have limitations on the API level, whereas others may have runtime limits, e.g. with OpenGL ES an implementation may just say GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS is 0 meaning no SSBOs in vertex shaders. (apparently the case on some embedded GPUs, presumably due to the tiled architecture, e.g. on Mali) So for now add a note to all the relevant QRhiShaderResourceBinding functions. It should be possible to make it work with fragment shaders to a degree at least, but for D3D we then have to deal with OMSetRenderTargetsAndUnorderedAccessViews and some remapping of binding points, whereas elsewhere they may be issues with missing or incorrect barriers. So do not go there now. Change-Id: Ib18949e0184626a9abf5bb72c6ef72bc1cb2e1fa Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* rhi: d3d11: Enable tessellation and geometry with some caveatsLaszlo Agocs2022-08-151-13/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | The caveat being having to manually create HLSL versions of the hull, domain, and geometry shaders in parallel with the Vulkan GLSL ones, while keeping the interfaces intact (stage inputs and outputs, cbuffer layouts, binding points/registers). This is not always trivial but typically doable in not very complicated case after inspecting the SPIRV-Cross-generated vertex/fragment code in the .qsb files. Once written, the HLSL files can be injected into a .qsb file with qsb -r. or the corresponding CMake syntax. Conceptually this is no different from how samplerExternalOES support is implemented for Multimedia. (there the problem is that the shaders cannot be compiled to SPIR-V to begin with, here it is that we cannot translate from SPIR-V, but in the end the workaround for both problems is effectively the same) The manual tests demonstrate this, both the tessellation and geometry apps work now with D3D out of the box. On the bright side, the implementation here in the the D3D backend of QRhi does not need to know about how the shaders got there in the QShader. So none of the implementation is dependent on this manual process. If some day qsb would start translating to these kind of shaders as well, it would all still work as-is. Change-Id: I32d9ab94e00174e4bd5b59ac814dfedef9f93ad1 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* rhi: Clean up some inconsistenciesLaszlo Agocs2022-07-121-11/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Some of the offsets are already quint32 in the API (vertex input attributes, dynamic offsets, offsets in draw calls), matching the reality of the underlying 3D APIs, but many buffer-related functions use int as of now, simply because that used to be the default choice, and the same goes for sizes (such as buffer or range sizes). This is not quite consistent and should be cleaned up if for nothing else then just to make the classes consistent, but also because no 3D API use a signed type for offsets, sizes, and strides. (except OpenGL for some) When it comes to strides (for vertex inputs and raw image texture uploads), those are already all quint32s. This is straightforward because most of the 3D APIs use 32-bit uints for these regardless of the architecture. Sizes and offsets are often architecture-dependent (Vulkan, Metal), but there is at least one API where they are always 32-bit even on 64-bit Windows (UINT == unsigned int, D3D11). In addition, we do not really care about buffer or texture data larger than 4 GB, at least not without realistic use cases and real world testing, which are quite unlikely to materialize for now (esp. since we still have the width/height of 2D textures limited to 16 or 32K in many cases even on desktops, whereas 2GB+ buffers are not guaranteed in practice even when an API seemingly allows it). In any case, the important change here is the signed->unsigned switch. A number of casts can now be removed here and there in the backends, because the offsets and sizes are now unsigned as well, matching the underlying API reality. The size can be potentially increased later on with minimal effort, if that becomes necessary for some reason. Change-Id: I404dbc365ac397eaeeb3bd2da9ce7eb98916da5f Reviewed-by: Inho Lee <inho.lee@qt.io> Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
* rhi: Fix up the instancing step rate typeLaszlo Agocs2022-07-071-1/+1
| | | | | | | | | | | | | | | This is a UINT/uint32_t/GLuint/NSUInteger in all APIs (with Metal being special due to being 64-bit in 64-bit apps whereas all others are 32-bit always, at least on 64-bit Windows) As the stride is already an uint32, follow suit for the step rate. There was no reason to have this as int in the first place. As an added bonus, some casts, that were previously needed when mapping to the underlying API reality, can now be removed. Change-Id: I8e0eef037bd795b637578dfc3e59dc2efaa5976c Reviewed-by: Christian Strømme <christian.stromme@qt.io>
* rhi: Keep track of pipeline creation timesLaszlo Agocs2022-07-051-14/+41
| | | | | | | | | | | | | | | | | | | | | Make our QRhiMemAllocStats struct a bit more generic, drop the memory allocation part in the naming, and use the same getter and struct for reporting some important timings. (we are free to rename for now, there are no users in other modules yet) The time spent in graphics (or compute) pipeline creation has a special relevance in particular with the modern APIs (as it is the single biggest potentially time consuming blocking operation), but also highly interesting with others like D3D11 simply because that's where we do the expensive source-to-intermediate compilation is HLSL source is provided. In order to see the effects of the various caching mechanisms (of which there can be confusingly many, on multiple levels), the ability to see how much time we spent on pipeline creation e.g. until we render the first view of an application can be pretty essential. Task-number: QTBUG-103802 Change-Id: I85dd056a39db7e6b25fb1f9d02e4c94298d22b41 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* rhi: Make it possible to query the backend name beforehandLaszlo Agocs2022-07-051-4/+13
| | | | | | | | | | | | | | | | The goal is to make it possible to implement QSGRhiSupport::backendName() in Qt Quick with just a single line: return QString::fromUtf8(QRhi::backendName(m_rhiBackend)); instead of duplicating the strings and the logic. Similarly, QBackingStoreRhiSupport can now drop its apiName() helper entirely. Change-Id: Ia8cbb1f1243539ed4d7a98e71dcc2ed56b017e40 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* rhi: Fix a doc snippetLaszlo Agocs2022-07-051-3/+6
| | | | | | | | | Docs are private for now, but it is still preferable that the code snippets in there are up-to-date. Change-Id: Icaf28d9b6a9ac029755ba241263f59d5091aa1b5 Reviewed-by: Inho Lee <inho.lee@qt.io> Reviewed-by: Christian Strømme <christian.stromme@qt.io>
* Fix typos in docs and commentsKai Köhne2022-06-151-2/+2
| | | | | | | | | Found by codespell Pick-to: 6.4 Change-Id: Ie3e301a23830c773a2e9aff487c702a223d246eb Reviewed-by: Nicholas Bennett <nicholas.bennett@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
* rhi: d3d11: Make the "pipeline" cache save/load functionalLaszlo Agocs2022-06-011-21/+53
| | | | | | | | | | | | | | | | | | | | | | | | There are no pipelines here of course. That's only for Vulkan. But the QRhi APIs provide a common interface for retrieving the serialized blob and pre-seeding the cache with a blob. The OpenGL backend already implements that interface via GL program binaries. We can do something similar with D3D, but it's a lot simpler: we just need to include the bytecode from HLSL->DXBC compilation (i.e. the result of D3DCompile() calls) and pick up the already present bytecode and skip the D3DCompile() call when applicable. Thus the mechanism is now available for Vulkan, OpenGL, and D3D11 as well. Has no effect whatsoever if EnablePipelineCacheLoadSave is not set at QRhi create() time. Also update the related docs. Task-number: QTBUG-103802 Change-Id: I91f1fb1f471bc7c654e26886a37c283066e842a8 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* rhi: Fix texture format doc typo and rephraseLaszlo Agocs2022-05-241-3/+3
| | | | | Change-Id: Ica4cc0fcea642eccfff7b53a65e7d1a428fd4dad Reviewed-by: Christian Strømme <christian.stromme@qt.io>
* Use SPDX license identifiersLucie Gérard2022-05-161-38/+2
| | | | | | | | | | | | | Replace the current license disclaimer in files by a SPDX-License-Identifier. Files that have to be modified by hand are modified. License files are organized under LICENSES directory. Task-number: QTBUG-67283 Change-Id: Id880c92784c40f3bbde861c0d93f58151c18b9f1 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
* rhi: Add a feature flag for non-fill polygon modesLaszlo Agocs2022-04-221-1/+10
| | | | | | | | It's one thing that this is not part of OpenGL ES, but it is optional even with Vulkan, with some mobile GPUs not offering the feature at all. Change-Id: I4e2c6642eccb0793e69074b4b6eeb2b7cef3516e Reviewed-by: Christian Strømme <christian.stromme@qt.io>
* rhi: Add explicit subclass for RTs from swapchainsLaszlo Agocs2022-04-051-10/+44
| | | | | | | | | | | | | | | | | | | | | | | | | | We want to enable gaining access to the underlying resource(s) by inspecting a QRhiRenderTarget. This is not currently possible for swapchains since there is nothing that references the actual QRhiSwapChain. To clean this up, make an explicit, new QRhiSwapChainRenderTarget subclass. Thus the logic already used in a couple of places to examine the resources attached to a QRhiTextureRenderTarget can now work with swapchain render targets too, by branching based on the resourceType(). This eliminates the somewhat odd setup where a "RenderTarget" resource is QRhiRenderTarget corresponding (but not exposing!) a swapchain, whereas a "TextureRenderTarget" is a QRhiTextureRenderTarget which is a subclass of QRhiRenderTarget. Now we correctly have an (abstract) base and two subclasses, one for each type of render targets. Besides, it allows us to clean up the oddly named Q...ReferenceRenderTarget classes in the backends, which initially tried to indicate that this "render target" merely references (or, in practice, is) a swapchain. We can now have a nice and symmetrical Q...SwapChainRenderTarget and Q...TextureRenderTarget naming scheme. Change-Id: Ib07e9be99a316eec67b94de0860e08f5f4638959 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* rhi: d3d11/vulkan: Allow passing in an array range overrideLaszlo Agocs2022-03-241-0/+22
| | | | | | | | | | | | | | | | | | Only (straightforwardly) implementable with modern APIs, and only really exists to handle special platform cases, such as when a video framework gives us a D3D texture array with D3D11_BIND_DECODER | D3D11_BIND_SHADER_RESOURCE which is only possible to use as a shader resource if the SRV selects a single array layer. Has no effect on the normal usage of texture arrays, where all array layers are exposed, and it is the shader that selects the layer when sampling or loading via the sampler2DArray. That continues to be the standard way to work with texture arrays. Change-Id: I0a656b605da21f50239b38abb83067e0208c1dbe Reviewed-by: Piotr Srebrny <piotr.srebrny@qt.io> Reviewed-by: Christian Strømme <christian.stromme@qt.io>
* Fix deprecated uses of QScopedPointerMårten Nordheim2022-03-081-3/+5
| | | | | | | | | By changing it to unique_ptr. Pick-to: 6.2 6.3 Change-Id: I91abb69445b537d4c95983ae735341882352b29d Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
* rhi: Add the long-pending probe() helper, with backing for MetalLaszlo Agocs2022-02-091-0/+48
| | | | | | | | | | | | | | | | | | | | | There is a TODO for this in Qt Quick from the 6.0 times. To decide upfront if Metal can be expected to function, or if a fallback to OpenGL needs to be triggered (especially important with macOS virtual machines, where, unlike any real macOS system, Metal may not be present at all), the scenegraph calls create() and then drops the result. The idea to make this less wasteful was back then to add a dedicated probing function which can, possibly, perform the checks in a more lightweight manner than full initialization. Implement this now, focusing on Metal. Brought to attention by QTBUG-100441: printing warnings about not having an MTLDevice is confusing in a Metal-less macOS VM, because it is not an actual error, only part of the probing at scenegraph initialization. We can now avoid printing confusing warnings there. Change-Id: Ie52c36af9224bedc3f5e4c23edb486d961c9f216 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* rhi: Code quality - remove defaults from switch enumsBen Fletcher2022-02-011-25/+8
| | | | | | | | | | | | | On code review of previous RHI patches it was noted that many switch on enum statements contain a default. This is discouraged as it prevents the compiler from automatically identifying switch statements that do not cover all enum cases. This patch addresses rhi base classes. Further patches required for specific backend implementations. Change-Id: Ib2bb30c66fd214b65a4ca7b787c7c610f3c313f5 Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
* rhi: Add the basic infrastructure for geometry shader supportBen Fletcher2022-01-311-0/+17
| | | | | | | | | | | | | | | | | | | | | .. but this will only be supported on Vulkan, OpenGL 3.2+, and Open GL ES 3.2+ for the time being. The situation is: - Vulkan is working. qsb accepts .geom files already, and QShader has existing geometry shader support. - OpenGL 3.2 and OpenGL ES 3.2 are working. - D3D11 is not working. D3D11 supports geometry shaders, but SPIRV- Cross does not support translating geometry shaders to HLSL. - Metal is not working. Metal does not directly support geometry shaders. Change-Id: Ieb7c44c58b8be5f2e2197bf5133cf6847e6c132d Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
* rhi: Add support for polygon fill modeBen Fletcher2022-01-311-0/+14
| | | | | | | | | | | | | | | | | Support for Polygon Mode (Triangle Fill Mode in Metal, Fill Mode in D3D) in the RHI graphics pipeline. Options are Fill and Line Status: OpenGL - ok Vulkan - ok Metal - ok D3D11 - ok OpenGL ES - does not support glPolygonMode. Change-Id: I20b7ef416624700c3dc8d1cbe6474f4ca3889db8 Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
* rhi: Fix tessellation support for OpenGLBen Fletcher2022-01-281-7/+7
| | | | | | | | | Added shader stage mapping for tessellation stages. Manual test rhi/tessellation now works for OpenGL. Change-Id: I7906b21e9d6e20883f17729f077dba57aa29f4fd Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
* rhi: Make sure pixelSize() to a texture rt is always up to dateLaszlo Agocs2022-01-251-0/+12
| | | | | | | | | This is an issue for QQuickWindow in practice, although it is not hit by our current tests. Pick-to: 6.3 Change-Id: Ia73704c1af6a82b2689ce7b844d3b0eb9a17ec18 Reviewed-by: Christian Strømme <christian.stromme@qt.io>
* rhi: Add the basic infrastructure for tessellation supportLaszlo Agocs2022-01-131-3/+41
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ...but this will only be supported with Vulkan and OpenGL 4.0+ and OpenGL ES 3.2+ for the time being. Taking the Vulkan model as our standard, the situation is the following: - Vulkan is ok, qsb secretly accepts .tesc and .tese files as input already (plus QShader already has the necessary plumbing when it comes to enums and such) To switch the tessellation domain origin to bottom left we require Vulkan 1.1 (don't bother with VK_KHR_maintenance2 on top of 1.0 at this point since 1.1 or 1.2 implementations should be common by now). The change is essential to allow the same evaluation shader to work with both OpenGL and Vulkan: this way we can use the same shader source, declaring the tessellation winding order as CCW, with both APIs. - OpenGL 4.0 and OpenGL ES 3.2 (or ES 3.1 with the Android extension pack, but we won't bother with checking that for now) can be made working without much complications, though we need to be careful when it comes to gathering and setting uniforms so that we do not leave the new tessellation stages out. We will stick to the Vulkan model in the sense that the inner and outer tessellation levels must be specified from the control shader, and cannot be specified from the host side, even though OpenGL would allow this. (basically the same story as with point size in vertex shaders) - D3D11 would be no problem API-wise, and we could likely implement the support for hull and domain shader stages in the backend, but SPIRV-Cross does not support translating tessellation shaders to HLSL. Attempting to feed in a .tesc or .tese file to qsb with --hlsl specified will always fail. One issue here is how hull shaders are structured, with the patchconstantfunc attribute specifying a separate function computing the patch constant data. With GLSL there is a single entry point in the tessellation control shader, which then performs both the calculations on the control points as well as the constant data (such as, the inner and outer tessellation factors). One option here is to inject handwritten HLSL shaders in the .qsb files using qsb's replace (-r) mode, but this is not exactly a viable universal solution. - Metal uses a different tessellation pipeline involving compute shaders. This needs more investigation but probably not something we can prioritize in practice. SPIRV-Cross does support this, generating a compute shader for control and a (post-)vertex shader for evaluation, presumably in order to enable MoltenVK to function when it comes to tessellation, but it is not clear yet how usable this is for us. Change-Id: Ic953c63850bda5bc912c7ac354425041b43157ef Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* rhi: Add queries for vertex input/output limitsLaszlo Agocs2022-01-121-0/+10
| | | | | | | | | | Mainly because we do have legacy code in the Qt 5 graphical effects that tries to dynamically determine the max number of varyings. Make it easier to port such code. Change-Id: I846cab2c2fe7b4cd473b5ced0146ca36f1c8169b Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Christian Strømme <christian.stromme@qt.io>
* rhi: Improve the handling of HDR capable texture formatsLaszlo Agocs2022-01-111-0/+17
| | | | | | | | | | | Add some sort of autotest for both RGBA16F and the new RGB10A2. The latter is introduced particularly because ideally we should have a texture format that corresponds to the D3D/Vulkan swapchain color buffer format with HDR10. Change-Id: I1e1bbb7c7e32cb3db89275900811c0bcaeac39d6 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* rhi: Add some docs for the hdr info queriesLaszlo Agocs2022-01-111-0/+55
| | | | | Change-Id: I9b3b62ac83642a7d3e474c991e572877b9e46ca5 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* rhi: Add support for separate image and sampler objectsLaszlo Agocs2022-01-061-8/+158
| | | | | | | | | | | | | | | | | | | | | For Direct 3D, Metal, and Vulkan this is natively supported. (and makes no difference in particular for D3D and Metal because they do not have the legacy combined image sampler concept anyways) With OpenGL it will work too, but this relies on SPIR-Cross magic and is still using a combined sampler (e.g. a sampler2D) in the GLSL shader. The GL backend walks back and forth in the mapping tables from the shader baker in order to make this work, which is presumably slightly more expensive than combined image samplers. Do note that combined image samplers (i.e. sampler2D in the shader and QRhiShaderResourceBinding::sampledTexture() in code) continue to be the primary, recommended way for any user of the rhi for the time being. Change-Id: I194721bc657b1ffbcc1bb79e6eadebe569a25087 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
* rhi: Expose HDR output info in a saner wayLaszlo Agocs2022-01-061-8/+27
| | | | | | | | | | Don't bother with exposing the IDXGIOutput6. Instead, report the values, just the ones that matter for tonemapping or transfer functions in a cross-platform way that's also prepared for Metal's different way of doing things. Change-Id: I28c7b6144f8267a9d3d44eff1e40697fb543385f Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* rhi: Drop the profiler for nowLaszlo Agocs2022-01-041-52/+78
| | | | | | | | | | | | | | | | | | | | | | | | | | | The system we inherited from the original Qt 5.14 introduction of QRhi is a text stream based solution where resource creation and frame timings are sent in a comma-separated format to a QIODevice. This, while useful to get insights about the number of resources at a given time, is not actively helpful. The frameworks built on top (Qt Quick, Qt Quick 3D) are expected to provide solutions for logging timings in a different way (e.g. via the QML Profiler). Similarly, tracking active resources and generating statistics from that is better handled on a higher level. The unique bits, such as the Vulkan memory allocator statistics and the GPU frame timestamps, are converted into APIs in QRhi. This way a user of QRhi can query it at any time and do whatever it sees fit with the data. When it comes to the GPU timestamps, that has a somewhat limited value due to the heavy asynchronousness, hence the callback based API. Nonetheless, this is still useful since it is the only means of reporting some frame timing data (an approx. elapsed milliseconds for a frame) from the GPU side. Change-Id: I67cd58b81aaa7e343c11731f9aa5b4804c2a1823 Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
* rhi: Add the basics for HDR swapchainsLaszlo Agocs2022-01-031-6/+56
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ...backed by support in the backends for D3D11 and Vulkan. Expose only what works in practice: scRGB with RGBA16F and HDR10 with RGB10A2 (or A2BGRA10 etc.). For general use, e.g. to render 2D/3D content, scRGB (i.e. extended sRGB linear) should be chosen because that is a linear space. On Windows with a HDR10 display (and an NVIDIA card) both of these are known to work, as long as Use HDR is enabled in the Settings for the display on which the window is created. When requesting a HDR format and it is not supported, we will fall back to the default SDR RGBA8/BGRA8 format. However, the behavior seems to be a bit weird with Vulkan and NVIDIA at least when there is a HDR display but Use HDR is set to Off: this seems to enable HDR mode for the lifetime of the window (with the usual set of black screens while switching over the entire display). Not sure why the driver does this. With D3D/DXGI, with fewer abstractions in the way, we can check upfront properly, so that will nicely fall back to the defaults regardless of why HDR is not available. Support can also be checked in advance via QRhiSwapChain::isFormatSupported() as long as the QWindow is available. (though with Vulkan, as said above, this also seems to ignore the Use HDR setting of Windows) Complications, such as moving a window from one screen to another, are currently not known how they behave. To be seen how this is handled by the Windows compositor. (from 1903 and up it is said to be able to automatically downconvert scRGB to SDR so perhaps moving from a HDR to a non-HDR screen would work - remains to be seen if this needs something more involved) When it comes to other platforms and potential future support: - based on its docs Android 8+ may support scRGB with Vulkan as-is on a suitable device/display, as long as the application declares android:colorMode="wideColorGamut" in the manifest. - for Metal the layer can be made EDR enabled and then e.g. MTLPixelFormatRGBA16Float/kCGColorSpaceExtendedLinearSRGB should work. However, this won't be added unless we can test it. - Linux is unknown. If one needs access to display specific values such as the min/max luminance when implementing tonemapping or a transfer function, that needs platform/API specific approaches, and sadly the kind of data exposed seems to vary, potentially making it difficult to maintain a single cross-platform logic. With D3D one can get the DXGI_OUTPUT_DESC1 from the IDXGIOutput6. This has the min/max luminances in nits and a bunch of other things. For convenience the output object is now exposed from the swapchain's nativeHandles() whenever the D3D backend is used at run time. For Metal one would presumably access maximumExtendedDynamicRangeColorComponentValue and co. in the NSScreen. Elsewhere one needs to rely on platform/winsys specific approaches, if there are any. Remains to be seen longer term if/how this needs/can be better supported. Change-Id: I2e61a0e062282d4bfdfba39655941c0f9a795112 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* rhi: Auto-rebuild rt by tracking attachment id and generationLaszlo Agocs2021-12-101-1/+35
| | | | | | | | | | | | | | | | | | | | | | | Unlike the shader resource binding lists that automatically recognize in setShaderResources() when a referenced QRhiResource has been rebuilt in the meantime (create() was called i.e. there may be completely different native objects underneath), QRhiTextureRenderTarget has no such thing. This leads to an asymmetric API and requires also rebuilding the rt whenever an attachment is rebuilt: rt = rhi->newTextureRenderTarget({ { texture } }) rt->create() cb->beginPass(rt, ...) texture->setPixelSize(...) texture->create() rt->create() // this should not be needed cb->beginPass(rt, ...) Avoid having to do that second rt->create(). Change-Id: If14eaa7aac3530950498bbdf834324d0741a7c4d Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* rhi: Expose the maximum uniform buffer range limitLaszlo Agocs2021-11-101-0/+15
| | | | | | | | Pick-to: 6.2 Task-number: QTBUG-97715 Change-Id: I7f0a52c410b9b77f735fb3b7fd33141674bb0cda Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* rhi: Extend docs regarding QImage and data lifetimeLaszlo Agocs2021-11-021-0/+11
| | | | | | Change-Id: I45e0e53af7e6ba084f6305c3097c6a0ff65fb458 Pick-to: 6.2 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* rhi: Add texture array supportLaszlo Agocs2021-10-291-23/+81
| | | | | | | | | | | | | | Arrays of textures have always been supported, but we will encounter cases when we need to work with texture array objects as well. Note that currently it is not possible to expose only a slice of the array to the shader, because there is no dedicated API in the SRB, and thus the same SRV/UAV (or equivalent) is used always, capturing all elements in the array. Therefore in the shader the last component of P in texture() is in range 0..array_size-1. Change-Id: I5a032ed016aeefbbcd743d5bfb9fbc49ba00a1fa Reviewed-by: Andy Nichols <andy.nichols@qt.io>
* Rhi: Document expectation for setGraphicsPipeline's pipeline argumentChristian Strømme2021-10-191-0/+3
| | | | | | | | | The backed expect the pipeline to be valid, so document it and assert if the set pipeline is a null pointer. Pick-to: 6.2 Change-Id: I72b3d0d11b8dc98240d17e13adf2b6ccbd71891d Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>