Skip to content

Commit

Permalink
rhi: Add D3D12 support
Browse files Browse the repository at this point in the history
- 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 <[email protected]>
Reviewed-by: Qt CI Bot <[email protected]>
  • Loading branch information
alpqr committed Feb 7, 2023
1 parent 19c32e7 commit 84fb0de
Show file tree
Hide file tree
Showing 25 changed files with 21,933 additions and 34 deletions.
10,565 changes: 10,565 additions & 0 deletions src/3rdparty/D3D12MemoryAllocator/D3D12MemAlloc.cpp

Large diffs are not rendered by default.

2,632 changes: 2,632 additions & 0 deletions src/3rdparty/D3D12MemoryAllocator/D3D12MemAlloc.h

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions src/3rdparty/D3D12MemoryAllocator/LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Copyright (c) 2019-2022 Advanced Micro Devices, Inc. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
From d83bc556c26b13e1a243c71628f75ef624de05bf Mon Sep 17 00:00:00 2001
From: Laszlo Agocs <[email protected]>
Date: Sat, 21 Jan 2023 20:07:00 +0100
Subject: [PATCH] Eliminate warnings in D3D12MA

Change-Id: If703c50cc1239248b94967edb4047868aaf07f1a
---
.../D3D12MemoryAllocator/D3D12MemAlloc.cpp | 23 ++++++++++++++++++-
.../D3D12MemoryAllocator/D3D12MemAlloc.h | 6 ++---
2 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/src/3rdparty/D3D12MemoryAllocator/D3D12MemAlloc.cpp b/src/3rdparty/D3D12MemoryAllocator/D3D12MemAlloc.cpp
index fe1856927f..f041ec13d8 100644
--- a/src/3rdparty/D3D12MemoryAllocator/D3D12MemAlloc.cpp
+++ b/src/3rdparty/D3D12MemoryAllocator/D3D12MemAlloc.cpp
@@ -132,6 +132,18 @@ especially to test compatibility with D3D12_RESOURCE_HEAP_TIER_1 on modern GPUs.
#define D3D12MA_CREATE_NOT_ZEROED_AVAILABLE 1
#endif

+#if defined(__clang__) || defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wsign-compare"
+#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
+#pragma GCC diagnostic ignored "-Wswitch"
+#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma GCC diagnostic ignored "-Wnonnull-compare"
+#endif
+
namespace D3D12MA
{
static constexpr UINT HEAP_TYPE_COUNT = 4;
@@ -7581,12 +7593,14 @@ void AllocatorPimpl::BuildStatsString(WCHAR** ppStatsString, BOOL detailedMap)
json.WriteString(L"HEAP_FLAG_ALLOW_DISPLAY");
if (flags & D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER)
json.WriteString(L"HEAP_FLAG_CROSS_ADAPTER");
+#ifdef __ID3D12Device8_INTERFACE_DEFINED__
if (flags & D3D12_HEAP_FLAG_HARDWARE_PROTECTED)
json.WriteString(L"HEAP_FLAG_HARDWARE_PROTECTED");
if (flags & D3D12_HEAP_FLAG_ALLOW_WRITE_WATCH)
json.WriteString(L"HEAP_FLAG_ALLOW_WRITE_WATCH");
if (flags & D3D12_HEAP_FLAG_ALLOW_SHADER_ATOMICS)
json.WriteString(L"HEAP_FLAG_ALLOW_SHADER_ATOMICS");
+#endif
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
if (flags & D3D12_HEAP_FLAG_CREATE_NOT_RESIDENT)
json.WriteString(L"HEAP_FLAG_CREATE_NOT_RESIDENT");
@@ -7607,9 +7621,12 @@ void AllocatorPimpl::BuildStatsString(WCHAR** ppStatsString, BOOL detailedMap)
| D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER
| D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES
| D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES
+#ifdef __ID3D12Device8_INTERFACE_DEFINED__
| D3D12_HEAP_FLAG_HARDWARE_PROTECTED
| D3D12_HEAP_FLAG_ALLOW_WRITE_WATCH
- | D3D12_HEAP_FLAG_ALLOW_SHADER_ATOMICS);
+ | D3D12_HEAP_FLAG_ALLOW_SHADER_ATOMICS
+#endif
+ );
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
flags &= ~(D3D12_HEAP_FLAG_CREATE_NOT_RESIDENT
| D3D12_HEAP_FLAG_CREATE_NOT_ZEROED);
@@ -10539,3 +10556,7 @@ VirtualBlock::~VirtualBlock()
#endif // _D3D12MA_VIRTUAL_BLOCK_FUNCTIONS
#endif // _D3D12MA_PUBLIC_INTERFACE
} // namespace D3D12MA
+
+#if defined(__clang__) || defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
diff --git a/src/3rdparty/D3D12MemoryAllocator/D3D12MemAlloc.h b/src/3rdparty/D3D12MemoryAllocator/D3D12MemAlloc.h
index 4ab7be318e..d80dcb1e89 100644
--- a/src/3rdparty/D3D12MemoryAllocator/D3D12MemAlloc.h
+++ b/src/3rdparty/D3D12MemoryAllocator/D3D12MemAlloc.h
@@ -151,9 +151,9 @@ class D3D12MA_API IUnknownImpl : public IUnknown
{
public:
virtual ~IUnknownImpl() = default;
- virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
- virtual ULONG STDMETHODCALLTYPE AddRef();
- virtual ULONG STDMETHODCALLTYPE Release();
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override;
+ ULONG STDMETHODCALLTYPE AddRef() override;
+ ULONG STDMETHODCALLTYPE Release() override;
protected:
virtual void ReleaseThis() { delete this; }
private:
--
2.33.0.windows.2

16 changes: 16 additions & 0 deletions src/3rdparty/D3D12MemoryAllocator/qt_attribution.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[
{
"Id": "D3D12MemoryAllocator",
"Name": "D3D12 Memory Allocator",
"QDocModule": "qtgui",
"Description": "D3D12 Memory Allocator",
"QtUsage": "Memory management for the D3D12 backend of QRhi.",

"Homepage": "https://github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator",
"Version": "f128d39b7a95b4235bd228d231646278dc6c24b2",
"License": "MIT License",
"LicenseId": "MIT",
"LicenseFile": "LICENSE.txt",
"Copyright": "Copyright (c) 2019-2022 Advanced Micro Devices, Inc. All rights reserved."
}
]
7 changes: 7 additions & 0 deletions src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ qt_internal_add_module(Gui
QT_QPA_DEFAULT_PLATFORM_NAME="${QT_QPA_DEFAULT_PLATFORM}"
INCLUDE_DIRECTORIES
../3rdparty/VulkanMemoryAllocator
../3rdparty/D3D12MemoryAllocator
LIBRARIES
Qt::CorePrivate
PUBLIC_LIBRARIES
Expand Down Expand Up @@ -402,6 +403,11 @@ qt_internal_extend_target(Gui CONDITION WIN32
rhi/qrhid3d11.cpp rhi/qrhid3d11_p.h
rhi/qrhid3d11_p_p.h
rhi/vs_test_p.h
rhi/qrhid3d12.cpp rhi/qrhid3d12_p.h
rhi/qrhid3d12_p_p.h
rhi/cs_mipmap_p.h
../3rdparty/D3D12MemoryAllocator/D3D12MemAlloc.h
../3rdparty/D3D12MemoryAllocator/D3D12MemAlloc.cpp
text/windows/qwindowsfontdatabase.cpp text/windows/qwindowsfontdatabase_p.h
text/windows/qwindowsfontdatabasebase.cpp text/windows/qwindowsfontdatabasebase_p.h
text/windows/qwindowsfontengine.cpp text/windows/qwindowsfontengine_p.h
Expand All @@ -417,6 +423,7 @@ qt_internal_extend_target(Gui CONDITION WIN32
dxgi
dxguid
dcomp
d3d12
)

if(QT_FEATURE_egl)
Expand Down
20 changes: 16 additions & 4 deletions src/gui/painting/qbackingstorerhisupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#ifdef Q_OS_WIN
#include <QtGui/private/qrhid3d11_p.h>
#include <QtGui/private/qrhid3d12_p.h>
#endif

#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
Expand Down Expand Up @@ -79,10 +80,16 @@ bool QBackingStoreRhiSupport::create()
#endif

#ifdef Q_OS_WIN
if (!rhi && m_config.api() == QPlatformBackingStoreRhiConfig::D3D11) {
QRhiD3D11InitParams params;
params.enableDebugLayer = m_config.isDebugLayerEnabled();
rhi = QRhi::create(QRhi::D3D11, &params, flags);
if (!rhi) {
if (m_config.api() == QPlatformBackingStoreRhiConfig::D3D11) {
QRhiD3D11InitParams params;
params.enableDebugLayer = m_config.isDebugLayerEnabled();
rhi = QRhi::create(QRhi::D3D11, &params, flags);
} else if (m_config.api() == QPlatformBackingStoreRhiConfig::D3D12) {
QRhiD3D12InitParams params;
params.enableDebugLayer = m_config.isDebugLayerEnabled();
rhi = QRhi::create(QRhi::D3D12, &params, flags);
}
}
#endif

Expand Down Expand Up @@ -195,6 +202,7 @@ QSurface::SurfaceType QBackingStoreRhiSupport::surfaceTypeForConfig(const QPlatf
QSurface::SurfaceType type = QSurface::RasterSurface;
switch (config.api()) {
case QPlatformBackingStoreRhiConfig::D3D11:
case QPlatformBackingStoreRhiConfig::D3D12:
type = QSurface::Direct3DSurface;
break;
case QPlatformBackingStoreRhiConfig::Vulkan:
Expand Down Expand Up @@ -223,6 +231,8 @@ QRhi::Implementation QBackingStoreRhiSupport::apiToRhiBackend(QPlatformBackingSt
return QRhi::Vulkan;
case QPlatformBackingStoreRhiConfig::D3D11:
return QRhi::D3D11;
case QPlatformBackingStoreRhiConfig::D3D12:
return QRhi::D3D12;
case QPlatformBackingStoreRhiConfig::Null:
return QRhi::Null;
default:
Expand Down Expand Up @@ -264,6 +274,8 @@ bool QBackingStoreRhiSupport::checkForceRhi(QPlatformBackingStoreRhiConfig *outC
#ifdef Q_OS_WIN
if (backend == QStringLiteral("d3d11") || backend == QStringLiteral("d3d"))
config.setApi(QPlatformBackingStoreRhiConfig::D3D11);
if (backend == QStringLiteral("d3d12"))
config.setApi(QPlatformBackingStoreRhiConfig::D3D12);
#endif
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
if (backend == QStringLiteral("metal"))
Expand Down
1 change: 1 addition & 0 deletions src/gui/painting/qplatformbackingstore.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ struct Q_GUI_EXPORT QPlatformBackingStoreRhiConfig
Metal,
Vulkan,
D3D11,
D3D12,
Null
};

Expand Down
22 changes: 22 additions & 0 deletions src/gui/rhi/MiniEngine_LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
The MIT License (MIT)

Copyright (c) 2015 Microsoft

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Loading

0 comments on commit 84fb0de

Please sign in to comment.