rhi: Make it a QPA-style private but semi-public API
qrhi.h, qshader.h, qshaderdescription.h (and qshaderbaker.h from shadertools; done separately) become "RHI APIs", following the concept of QPA APIs. Mirror completely what is done for QPA headers, but using the "rhi" prefix for the headers. This involves updating syncqt to handle the new category of headers. (a note on the regex: matching everything starting with "qrhi" is not acceptable due to incorrectly matching existing and future headers, hence specifying the four header names explicitly) There is going to be one difference to QPA: the documentation for everything RHI is going to be public and part of the regular docs, not hidden with \internal. In addition to the header renaming and adding the comments and documentation notes and warnings, there is one significant change here: there is no longer a need to do API-specific includes, such as qrhid3d11[_p].h, qrhivulkan[_p].h, etc. These are simply merged into a single header that is then included from qrhi.h. This means that users within Qt, and any future applications can just do #include <rhi/qrhi.h> (or rhi/qshader.h if the QRhi stuff is not relevant), no other headers are needed. There are no changes to functionality in this patch. Only the documentation is expanded, quite a lot, to eliminate all qdoc warnings and make the generated API docs complete. An example, with a quite extensive doc page is added as well. Task-number: QTBUG-113331 Change-Id: I91c749826348f14320cb335b1c83e9d1ea2b1d8b Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
parent
30a8e79243
commit
1dd8b5ceec
@ -72,7 +72,7 @@ function(qt_copy_framework_headers target)
|
||||
|
||||
set(options)
|
||||
set(oneValueArgs)
|
||||
set(multiValueArgs PUBLIC PRIVATE QPA)
|
||||
set(multiValueArgs PUBLIC PRIVATE QPA RHI)
|
||||
cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
qt_internal_get_framework_info(fw ${target})
|
||||
@ -80,10 +80,11 @@ function(qt_copy_framework_headers target)
|
||||
set(output_dir_PUBLIC "${output_dir}/${fw_versioned_header_dir}")
|
||||
set(output_dir_PRIVATE "${output_dir}/${fw_private_module_header_dir}/private")
|
||||
set(output_dir_QPA "${output_dir}/${fw_private_module_header_dir}/qpa")
|
||||
set(output_dir_RHI "${output_dir}/${fw_private_module_header_dir}/rhi")
|
||||
|
||||
|
||||
set(out_files)
|
||||
foreach(type IN ITEMS PUBLIC PRIVATE QPA)
|
||||
foreach(type IN ITEMS PUBLIC PRIVATE QPA RHI)
|
||||
set(fw_output_header_dir "${output_dir_${type}}")
|
||||
foreach(hdr IN LISTS arg_${type})
|
||||
get_filename_component(in_file_path ${hdr} ABSOLUTE)
|
||||
|
@ -30,6 +30,7 @@ macro(qt_internal_get_internal_add_module_keywords option_args single_args multi
|
||||
EXTERNAL_HEADERS_DIR
|
||||
PRIVATE_HEADER_FILTERS
|
||||
QPA_HEADER_FILTERS
|
||||
RHI_HEADER_FILTERS
|
||||
HEADER_SYNC_SOURCE_DIRECTORY
|
||||
${__default_target_info_args}
|
||||
)
|
||||
@ -115,6 +116,10 @@ endfunction()
|
||||
# The regular expressions that filter QPA header files out of target sources.
|
||||
# The value must use the following format 'regex1|regex2|regex3'.
|
||||
#
|
||||
# RHI_HEADER_FILTERS
|
||||
# The regular expressions that filter RHI header files out of target sources.
|
||||
# The value must use the following format 'regex1|regex2|regex3'.
|
||||
#
|
||||
# HEADER_SYNC_SOURCE_DIRECTORY
|
||||
# The source directory for header sync procedure. Header files outside this directory will be
|
||||
# ignored by syncqt. The specifying this directory allows to skip the parsing of the whole
|
||||
@ -447,6 +452,13 @@ function(qt_internal_add_module target)
|
||||
set_target_properties(${target}
|
||||
PROPERTIES _qt_module_qpa_headers_filter_regex "${qpa_filter_regex}")
|
||||
|
||||
set(rhi_filter_regex "")
|
||||
if(arg_RHI_HEADER_FILTERS)
|
||||
set(rhi_filter_regex "${arg_RHI_HEADER_FILTERS}")
|
||||
endif()
|
||||
set_target_properties(${target}
|
||||
PROPERTIES _qt_module_rhi_headers_filter_regex "${rhi_filter_regex}")
|
||||
|
||||
set(private_filter_regex ".+_p(ch)?\\.h")
|
||||
if(arg_PRIVATE_HEADER_FILTERS)
|
||||
set(private_filter_regex "${private_filter_regex}|${arg_PRIVATE_HEADER_FILTERS}")
|
||||
@ -892,6 +904,7 @@ function(qt_finalize_module target)
|
||||
PUBLIC ${module_headers_public} "${module_depends_header}"
|
||||
PRIVATE ${module_headers_private}
|
||||
QPA ${module_headers_qpa}
|
||||
RHI ${module_headers_rhi}
|
||||
)
|
||||
|
||||
qt_finalize_framework_headers_copy(${target})
|
||||
@ -924,6 +937,7 @@ endfunction()
|
||||
# * foo_versioned_inner_include_dir with the value "QtCore/6.2.0/QtCore"
|
||||
# * foo_private_include_dir with the value "QtCore/6.2.0/QtCore/private"
|
||||
# * foo_qpa_include_dir with the value "QtCore/6.2.0/QtCore/qpa"
|
||||
# * foo_rhi_include_dir with the value "QtCore/6.2.0/QtCore/rhi"
|
||||
# * foo_interface_name the interface name of the module stored in _qt_module_interface_name
|
||||
# property, e.g. Core.
|
||||
#
|
||||
@ -946,6 +960,9 @@ endfunction()
|
||||
# * foo_<build|install>_qpa_include_dir with
|
||||
# qtbase_build_dir/include/QtCore/6.2.0/QtCore/qpa for build interface and
|
||||
# include/QtCore/6.2.0/QtCore/qpa for install interface.
|
||||
# * foo_<build|install>_rhi_include_dir with
|
||||
# qtbase_build_dir/include/QtCore/6.2.0/QtCore/rhi for build interface and
|
||||
# include/QtCore/6.2.0/QtCore/rhi for install interface.
|
||||
# The following values are set by the function and might be useful in caller's scope:
|
||||
# * repo_install_interface_include_dir contains path to the top-level repository include directory,
|
||||
# e.g. qtbase_build_dir/include
|
||||
@ -980,6 +997,8 @@ the different base name for the module info variables.")
|
||||
"${${result}_versioned_inner_include_dir}/private")
|
||||
set("${result}_qpa_include_dir"
|
||||
"${${result}_versioned_inner_include_dir}/qpa")
|
||||
set("${result}_rhi_include_dir"
|
||||
"${${result}_versioned_inner_include_dir}/rhi")
|
||||
|
||||
# Module build interface directories
|
||||
set(repo_build_interface_include_dir "${QT_BUILD_DIR}/include")
|
||||
@ -993,6 +1012,8 @@ the different base name for the module info variables.")
|
||||
"${repo_build_interface_include_dir}/${${result}_private_include_dir}")
|
||||
set("${result}_build_interface_qpa_include_dir"
|
||||
"${repo_build_interface_include_dir}/${${result}_qpa_include_dir}")
|
||||
set("${result}_build_interface_rhi_include_dir"
|
||||
"${repo_build_interface_include_dir}/${${result}_rhi_include_dir}")
|
||||
|
||||
# Module install interface directories
|
||||
set(repo_install_interface_include_dir "${INSTALL_INCLUDEDIR}")
|
||||
@ -1006,6 +1027,8 @@ the different base name for the module info variables.")
|
||||
"${repo_install_interface_include_dir}/${${result}_private_include_dir}")
|
||||
set("${result}_install_interface_qpa_include_dir"
|
||||
"${repo_install_interface_include_dir}/${${result}_qpa_include_dir}")
|
||||
set("${result}_install_interface_rhi_include_dir"
|
||||
"${repo_install_interface_include_dir}/${${result}_rhi_include_dir}")
|
||||
|
||||
set("${result}" "${module}" PARENT_SCOPE)
|
||||
set("${result}_versioned" "${module_versioned}" PARENT_SCOPE)
|
||||
@ -1019,6 +1042,7 @@ the different base name for the module info variables.")
|
||||
"${${result}_versioned_inner_include_dir}" PARENT_SCOPE)
|
||||
set("${result}_private_include_dir" "${${result}_private_include_dir}" PARENT_SCOPE)
|
||||
set("${result}_qpa_include_dir" "${${result}_qpa_include_dir}" PARENT_SCOPE)
|
||||
set("${result}_rhi_include_dir" "${${result}_rhi_include_dir}" PARENT_SCOPE)
|
||||
set("${result}_interface_name" "${module_interface_name}" PARENT_SCOPE)
|
||||
|
||||
# Setting module build interface directories in parent scope
|
||||
@ -1033,6 +1057,8 @@ the different base name for the module info variables.")
|
||||
"${${result}_build_interface_private_include_dir}" PARENT_SCOPE)
|
||||
set("${result}_build_interface_qpa_include_dir"
|
||||
"${${result}_build_interface_qpa_include_dir}" PARENT_SCOPE)
|
||||
set("${result}_build_interface_rhi_include_dir"
|
||||
"${${result}_build_interface_rhi_include_dir}" PARENT_SCOPE)
|
||||
|
||||
# Setting module install interface directories in parent scope
|
||||
set(repo_install_interface_include_dir "${repo_install_interface_include_dir}" PARENT_SCOPE)
|
||||
@ -1046,6 +1072,8 @@ the different base name for the module info variables.")
|
||||
"${${result}_install_interface_private_include_dir}" PARENT_SCOPE)
|
||||
set("${result}_install_interface_qpa_include_dir"
|
||||
"${${result}_install_interface_qpa_include_dir}" PARENT_SCOPE)
|
||||
set("${result}_install_interface_rhi_include_dir"
|
||||
"${${result}_install_interface_rhi_include_dir}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(qt_internal_list_to_json_array out_var list_var)
|
||||
@ -1153,7 +1181,7 @@ endfunction()
|
||||
function(qt_internal_install_module_headers target)
|
||||
set(options)
|
||||
set(one_value_args)
|
||||
set(multi_value_args PUBLIC PRIVATE QPA)
|
||||
set(multi_value_args PUBLIC PRIVATE QPA RHI)
|
||||
cmake_parse_arguments(arg "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})
|
||||
|
||||
qt_internal_module_info(module ${target})
|
||||
@ -1178,6 +1206,7 @@ function(qt_internal_install_module_headers target)
|
||||
PUBLIC ${arg_PUBLIC}
|
||||
PRIVATE ${arg_PRIVATE}
|
||||
QPA ${arg_QPA}
|
||||
RHI ${arg_RHI}
|
||||
)
|
||||
else()
|
||||
if(arg_PUBLIC)
|
||||
@ -1191,6 +1220,9 @@ function(qt_internal_install_module_headers target)
|
||||
if(arg_QPA)
|
||||
qt_install(FILES ${arg_QPA} DESTINATION "${module_install_interface_qpa_include_dir}")
|
||||
endif()
|
||||
if(arg_RHI)
|
||||
qt_install(FILES ${arg_RHI} DESTINATION "${module_install_interface_rhi_include_dir}")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
@ -1198,6 +1230,7 @@ function(qt_internal_collect_module_headers out_var target)
|
||||
set(${out_var}_public "")
|
||||
set(${out_var}_private "")
|
||||
set(${out_var}_qpa "")
|
||||
set(${out_var}_rhi "")
|
||||
set(${out_var}_all "")
|
||||
|
||||
qt_internal_get_target_sources(sources ${target})
|
||||
@ -1215,6 +1248,7 @@ function(qt_internal_collect_module_headers out_var target)
|
||||
get_target_property(public_filter ${target} _qt_module_public_headers_filter_regex)
|
||||
get_target_property(private_filter ${target} _qt_module_private_headers_filter_regex)
|
||||
get_target_property(qpa_filter ${target} _qt_module_qpa_headers_filter_regex)
|
||||
get_target_property(rhi_filter ${target} _qt_module_rhi_headers_filter_regex)
|
||||
|
||||
set(condition_independent_headers_warning "")
|
||||
foreach(file_path IN LISTS sources)
|
||||
@ -1259,6 +1293,8 @@ function(qt_internal_collect_module_headers out_var target)
|
||||
list(APPEND ${out_var}_all "${file_path}")
|
||||
if(qpa_filter AND file_name MATCHES "${qpa_filter}")
|
||||
list(APPEND ${out_var}_qpa "${file_path}")
|
||||
elseif(rhi_filter AND file_name MATCHES "${rhi_filter}")
|
||||
list(APPEND ${out_var}_rhi "${file_path}")
|
||||
elseif(private_filter AND file_name MATCHES "${private_filter}")
|
||||
list(APPEND ${out_var}_private "${file_path}")
|
||||
elseif((NOT public_filter OR file_name MATCHES "${public_filter}")
|
||||
@ -1282,7 +1318,7 @@ function(qt_internal_collect_module_headers out_var target)
|
||||
endif()
|
||||
|
||||
|
||||
set(header_types public private qpa)
|
||||
set(header_types public private qpa rhi)
|
||||
set(has_header_types_properties "")
|
||||
foreach(header_type IN LISTS header_types)
|
||||
get_target_property(current_propety_value ${target} _qt_module_has_${header_type}_headers)
|
||||
@ -1304,5 +1340,6 @@ function(qt_internal_collect_module_headers out_var target)
|
||||
_qt_module_has_public_headers
|
||||
_qt_module_has_private_headers
|
||||
_qt_module_has_qpa_headers
|
||||
_qt_module_has_rhi_headers
|
||||
)
|
||||
endfunction()
|
||||
|
@ -211,6 +211,7 @@ function(qt_get_qmake_module_name result module)
|
||||
string(REGEX REPLACE "^Qt6" "" module "${module}")
|
||||
string(REGEX REPLACE "Private$" "_private" module "${module}")
|
||||
string(REGEX REPLACE "Qpa$" "_qpa_lib_private" module "${module}")
|
||||
string(REGEX REPLACE "Rhi$" "_rhi_lib_private" module "${module}")
|
||||
string(TOLOWER "${module}" module)
|
||||
set(${result} ${module} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
@ -79,6 +79,7 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
|
||||
endif()
|
||||
|
||||
get_target_property(qpa_filter_regex ${target} _qt_module_qpa_headers_filter_regex)
|
||||
get_target_property(rhi_filter_regex ${target} _qt_module_rhi_headers_filter_regex)
|
||||
get_target_property(private_filter_regex ${target} _qt_module_private_headers_filter_regex)
|
||||
|
||||
# We need to use the real paths since otherwise it may lead to the invalid work of the
|
||||
@ -96,6 +97,12 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
|
||||
)
|
||||
endif()
|
||||
|
||||
if(rhi_filter_regex)
|
||||
set(rhi_filter_argument
|
||||
-rhiHeadersFilter "${rhi_filter_regex}"
|
||||
)
|
||||
endif()
|
||||
|
||||
set(common_syncqt_arguments
|
||||
-module "${module}"
|
||||
-sourceDir "${source_dir_real}"
|
||||
@ -104,8 +111,10 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
|
||||
-includeDir "${module_build_interface_include_dir}"
|
||||
-privateIncludeDir "${module_build_interface_private_include_dir}"
|
||||
-qpaIncludeDir "${module_build_interface_qpa_include_dir}"
|
||||
-rhiIncludeDir "${module_build_interface_rhi_include_dir}"
|
||||
-generatedHeaders ${module_headers_generated}
|
||||
${qpa_filter_argument}
|
||||
${rhi_filter_argument}
|
||||
${public_namespaces_filter}
|
||||
${non_qt_module_argument}
|
||||
${internal_module_argument}
|
||||
|
@ -5,3 +5,4 @@ if(NOT TARGET Qt6::Gui)
|
||||
return()
|
||||
endif()
|
||||
qt_internal_add_example(rasterwindow)
|
||||
qt_internal_add_example(rhiwindow)
|
||||
|
BIN
examples/gui/doc/images/rhiwindow_example.jpg
Normal file
BIN
examples/gui/doc/images/rhiwindow_example.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
439
examples/gui/doc/src/rhiwindow.qdoc
Normal file
439
examples/gui/doc/src/rhiwindow.qdoc
Normal file
@ -0,0 +1,439 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
|
||||
|
||||
/*!
|
||||
\example rhiwindow
|
||||
\title RHI Window Example
|
||||
|
||||
\brief This example shows how to create a minimal QWindow-based
|
||||
application using QRhi.
|
||||
|
||||
\image rhiwindow_example.jpg
|
||||
|
||||
Qt 6.6 starts offering its accelerated 3D API and shader abstraction layer
|
||||
for application use as well. Applications can now use the same 3D graphics
|
||||
classes Qt itself uses to implement the Qt Quick scenegraph or the Qt Quick
|
||||
3D engine. In earlier Qt versions QRhi and the related classes were all
|
||||
private APIs. From 6.6 on these classes are in a similar category as QPA
|
||||
family of classes: neither fully public nor private, but something
|
||||
in-between, with a more limited compatibility promise compared to public
|
||||
APIs. On the other hand, QRhi and the related classes now come with full
|
||||
documentation similarly to public APIs.
|
||||
|
||||
There are multiple ways to use QRhi, the example here shows the most
|
||||
low-level approach: targeting a QWindow, while not using Qt Quick, Qt Quick
|
||||
3D, or Widgets in any form, and setting up all the rendering and windowing
|
||||
infrastructure in the application.
|
||||
|
||||
In contrast, when writing a QML application with Qt Quick or Qt Quick 3D,
|
||||
and wanting to add QRhi-based rendering to it, such an application is going
|
||||
to rely on the window and rendering infrastructure Qt Quick has already
|
||||
initialized, and it is likely going to query an existing QRhi instance from
|
||||
the QQuickWindow. There dealing with QRhi::create(), platform/API specifics
|
||||
such as \l{QVulkanInstance}{Vulkan instances}, or correctly handling
|
||||
\l{QExposeEvent}{expose} and resize events for the window are all managed
|
||||
by Qt Quick. Whereas in this example, all that is managed and taken care
|
||||
of by the application itself.
|
||||
|
||||
\note For QWidget-based applications in particular, it should be noted that
|
||||
QWidget::createWindowContainer() allows embedding a QWindow (backed by a
|
||||
native window) into the widget-based user interface. Therefore, the \c
|
||||
HelloWindow class from this example is reusable in QWidget-based
|
||||
applications, assuming the necessary initialization from \c main() is in
|
||||
place as well.
|
||||
|
||||
\section1 3D API Support
|
||||
|
||||
The application supports all the current \l{QRhi::Implementation}{QRhi
|
||||
backends}. When no command-line arguments are specified, platform-specific
|
||||
defaults are used: Direct 3D 11 on Windows, OpenGL on Linux, Metal on
|
||||
macOS/iOS.
|
||||
|
||||
Running with \c{--help} shows the available command-line options:
|
||||
|
||||
\list
|
||||
\li -d or --d3d11 for Direct 3D 11
|
||||
\li -D or --d3d12 for Direct 3D 12
|
||||
\li -m or --metal for Metal
|
||||
\li -v or --vulkan for Vulkan
|
||||
\li -g or --opengl for OpenGL or OpenGL ES
|
||||
\li -n or --null for the \l{QRhi::Null}{Null backend}
|
||||
\endlist
|
||||
|
||||
\section1 Build System Notes
|
||||
|
||||
This application relies solely on the Qt GUI module. It does not use Qt
|
||||
Widgets or Qt Quick.
|
||||
|
||||
In order to access the RHI APIs, which are available to all Qt applications
|
||||
but come with a limited compatibility promise, the \c target_link_libraries
|
||||
CMake command lists \c{Qt6::GuiPrivate}. This is what enables the
|
||||
\c{#include <rhi/qrhi.h>} include statement to compile successfully.
|
||||
|
||||
\section1 Features
|
||||
|
||||
The application features:
|
||||
|
||||
\list
|
||||
|
||||
\li A resizable QWindow,
|
||||
|
||||
\li a swapchain and depth-stencil buffer that properly follows the size of
|
||||
the window,
|
||||
|
||||
\li logic to initialize, render, and tear down at the appropriate time
|
||||
based on events such as \l QExposeEvent and \l QPlatformSurfaceEvent,
|
||||
|
||||
\li rendering a fullscreen textured quad, using a texture the contents of
|
||||
which is generated in a QImage via QPainter (using the raster paint engine,
|
||||
i.e. the generating of the image's pixel data is all CPU-based, that data
|
||||
is then uploaded into a GPU texture),
|
||||
|
||||
\li rendering a triangle with blending and depth testing enabled, using a
|
||||
perspective projection, while applying a model transform that changes on
|
||||
every frame,
|
||||
|
||||
\li an efficient, cross-platform render loop using
|
||||
\l{QWindow::requestUpdate()}{requestUpdate()}.
|
||||
|
||||
\endlist
|
||||
|
||||
\section1 Shaders
|
||||
|
||||
The application uses two sets of vertex and fragment shader pairs:
|
||||
|
||||
\list
|
||||
|
||||
\li one for the fullscreen quad, which uses no vertex inputs and the
|
||||
fragment shader samples a texture (\c quad.vert, \c quad.frag),
|
||||
|
||||
\li and another pair for the triangle, where vertex positions and colors
|
||||
are provided in a vertex buffer and a modelview-projection matrix is
|
||||
provided in a uniform buffer (\c color.vert, \c color.frag).
|
||||
|
||||
\endlist
|
||||
|
||||
The shaders are written as Vulkan-compatible GLSL source code.
|
||||
|
||||
Due to being a Qt GUI module example, this example cannot have a dependency
|
||||
on the \l{Qt Shader Tools} module. This means that CMake helper functions
|
||||
such as \c{qt_add_shaders} are not available for use. Therefore, the
|
||||
example has the pre-processed \c{.qsb} files included in the
|
||||
\c{shaders/prebuilt} folder, and they are simply included within the
|
||||
executable via \c{qt_add_resources}. This approach is not generally
|
||||
recommended for applications, consider rather using \l{Qt Shader Tools
|
||||
Build System Integration}{qt_add_shaders}, which avoids the need to
|
||||
manually generate and manage the \c{.qsb} files.
|
||||
|
||||
To generate the \c{.qsb} files for this example, the command \c{qsb --qt6
|
||||
color.vert -o prebuilt/color.vert.qsb} etc. was used. This leads to
|
||||
compiling to \l{https://www.khronos.org/spir/}{SPIR-V} and than transpiling
|
||||
into GLSL (\c{100 es} and \c 120), HLSL (5.0), and MSL (1.2). All the
|
||||
shader versions are then packed together into a QShader and serialized to
|
||||
disk.
|
||||
|
||||
\section1 API-specific Initialization
|
||||
|
||||
For some of the 3D APIs the main() function has to perform the appropriate
|
||||
API-specific initialiation, e.g. to create a QVulkanInstance when using
|
||||
Vulkan. For OpenGL we have to ensure a depth buffer is available, this is
|
||||
done via QSurfaceFormat. These steps are not in the scope of QRhi since
|
||||
QRhi backends for OpenGL or Vulkan build on the existing Qt facilities such
|
||||
as QOpenGLContext or QVulkanInstance.
|
||||
|
||||
\snippet rhiwindow/main.cpp api-setup
|
||||
|
||||
\note For Vulkan, note how
|
||||
QRhiVulkanInitParams::preferredInstanceExtensions() is taken into account
|
||||
to ensure the appropriate extensions are enabled.
|
||||
|
||||
\c HelloWindow is a subclass of \c RhiWindow, which in turn is a QWindow.
|
||||
\c RhiWindow contains everything needed to manage a resizable window with
|
||||
a\ swapchain (and depth-stencil buffer), and is potentially reusable in
|
||||
other applications as well. \c HelloWindow contains the rendering logic
|
||||
specific to this particular example application.
|
||||
|
||||
In the QWindow subclass constructor the surface type is set based on the
|
||||
selected 3D API.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp rhiwindow-ctor
|
||||
|
||||
Creating and initializing a QRhi object is implemented in
|
||||
RhiWindow::init(). Note that this is invoked only when the window is
|
||||
\c renderable, which is indicated by an \l{QExposeEvent}{expose event}.
|
||||
|
||||
Depending on which 3D API we use, the appropriate InitParams struct needs
|
||||
to be passed to QRhi::create(). With OpenGL for example, a
|
||||
QOffscreenSurface (or some other QSurface) must be created by the
|
||||
application and provided for use to the QRhi. With Vulkan, a successfully
|
||||
initialized QVulkanInstance is required. Others, such as Direct 3D or Metal
|
||||
need no additional information to be able to initialize.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp rhi-init
|
||||
|
||||
Apart from this, everything else, all the rendering code, is fully
|
||||
cross-platform and has no branching or conditions specific to any of the 3D
|
||||
API.
|
||||
|
||||
\section1 Expose Events
|
||||
|
||||
What \c renderable exactly means is platform-specific. For example, on
|
||||
macOS a window that is fully obscured (fully behind some other window) is
|
||||
not renderable, whereas on Windows obscuring has no significance.
|
||||
Fortunately, the application needs no special knowledge about this: Qt's
|
||||
platform plugins abstract the differences behind the expose event. However,
|
||||
the \l{QWindow::exposeEvent()}{exposeEvent()} reimplementation also needs
|
||||
to be aware that an empty output size (e.g. width and height of 0) is also
|
||||
something that should be treated as a non-renderable situation. On Windows
|
||||
for example, this is what is going to happen when minimizing the window.
|
||||
Hence the check based on QRhiSwapChain::surfacePixelSize().
|
||||
|
||||
This implementation of expose event handling attempts to be robust, safe,
|
||||
and portable. Qt Quick itself also implements a very similar logic in its
|
||||
render loops.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp expose
|
||||
|
||||
In RhiWindow::render(), which is invoked in response to the
|
||||
\l{QEvent::UpdateRequest}{UpdateRequest} event generated by
|
||||
\l{QWindow::requestUpdate()}{requestUpdate()}, the following check is in
|
||||
place, to prevent attempting to render when the swapchain initialization
|
||||
failed, or when the window became non-renderable.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp render-precheck
|
||||
|
||||
\section1 Swapchain, Depth-Stencil buffer, and Resizing
|
||||
|
||||
To render to the QWindow, a QRhiSwapChain is needed. In addition, a
|
||||
QRhiRenderBuffer acting as the depth-stencil buffer is created as well
|
||||
since the application demonstrates how depth testing can be enabled in a
|
||||
graphics pipeline. With some legacy 3D APIs managing the depth/stencil
|
||||
buffer for a window is part of the corresponding windowing system interface
|
||||
API (EGL, WGL, GLX, etc., meaning the depth/stencil buffer is implicitly
|
||||
managed together with the \c{window surface}), whereas with modern APIs
|
||||
managing the depth-stencil buffer for a window-based render target is no
|
||||
different from offscreen render targets. QRhi abstracts this, but for best
|
||||
performance it still needs to be indicated that the QRhiRenderBuffer is
|
||||
\l{QRhiRenderBuffer::UsedWithSwapChainOnly}{used with together with a
|
||||
QRhiSwapChain}.
|
||||
|
||||
The QRhiSwapChain is associated with the QWindow and the depth/stencil
|
||||
buffer.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp swapchain-data
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp swapchain-init
|
||||
|
||||
When the window size changes, the swapchain needs to be resized as well.
|
||||
This is implemented in resizeSwapChain().
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp swapchain-resize
|
||||
|
||||
Unlike other QRhiResource subclasses, QRhiSwapChain features slightly
|
||||
different semantics when it comes to its create-function. As the name,
|
||||
\l{QRhiSwapChain::createOrResize()}{createOrResize()}, suggests, this needs
|
||||
to be called whenever it is known that the output window size may be out of
|
||||
sync with what the swapchain was last initialized. The associated
|
||||
QRhiRenderBuffer for depth-stencil gets its
|
||||
\l{QRhiRenderBuffer::pixelSize()}{size} set automatically, and
|
||||
\l{QRhiRenderBuffer::create()}{create()} is called on it implicitly from the
|
||||
swapchain's createOrResize().
|
||||
|
||||
This is also a convenient place to (re)calculate the projection and view
|
||||
matrices since the perspective projection we set up depends on the output
|
||||
aspect ratio.
|
||||
|
||||
\note To eliminate coordinate system differences, the
|
||||
\l{QRhi::clipSpaceCorrMatrix()}{a backend/API-specific "correction" matrix}
|
||||
is queried from QRhi and baked in to the projection matrix. This is what
|
||||
allows the application to work with OpenGL-style vertex data, assuming a
|
||||
coordinate system with the origin at the bottom-left.
|
||||
|
||||
The resizeSwapChain() function is called from RhiWindow::render() when it
|
||||
is discovered that the currently reported size is not the same anymore as
|
||||
what the swapchain was last initialized with.
|
||||
|
||||
See QRhiSwapChain::currentPixelSize() and QRhiSwapChain::surfacePixelSize()
|
||||
for further details.
|
||||
|
||||
High DPI support is built-in: the sizes, as the naming indicates, are
|
||||
always in pixels, taking the window-specific
|
||||
\l{QWindow::devicePixelRatio()}{scale factor} into account. On the QRhi
|
||||
(and 3D API) level there is no concept of high DPI scaling, everything is
|
||||
always in pixels. This means that a QWindow with a size() of 1280x720 and
|
||||
a devicePixelRatio() of 2 is a render target (swapchain) with a (pixel) size
|
||||
of 2560x1440.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp render-resize
|
||||
|
||||
\section1 Render Loop
|
||||
|
||||
The application renders continuously, throttled by the presentation rate
|
||||
(vsync). This is ensured by calling
|
||||
\l{QWindow::requestUpdate()}{requestUpdate()} from RhiWindow::render() when
|
||||
the currently recorded frame has been submitted.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp request-update
|
||||
|
||||
This eventually leads to getting a \l{QEvent::UpdateRequest}{UpdateRequest}
|
||||
event. This is handled in the reimplementation of event().
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp event
|
||||
|
||||
\section1 Resource and Pipeline Setup
|
||||
|
||||
The application records a single render pass that issues two draw calls,
|
||||
with two different graphics pipelines. One is the "background", with the
|
||||
texture containing the QPainter-generated image, then a single triangle is
|
||||
rendered on top with blending enabled.
|
||||
|
||||
The vertex and uniform buffer used with the triangle is created like this.
|
||||
The size of the uniform buffer is 68 bytes since the shader specific a \c
|
||||
mat4 and a \c float member in the uniform block. Watch out for the
|
||||
\l{https://registry.khronos.org/OpenGL/specs/gl/glspec45.core.pdf#page=159}{std140
|
||||
layout rules}. This presents no surprises in this example since the \c
|
||||
float member that follows the \c mat4 has the correct alignment without any
|
||||
additional padding, but it may become relevant in other applications,
|
||||
especially when working with types such as \c vec2 or \c vec3. When in
|
||||
doubt, consider checking the QShaderDescription for the
|
||||
\l{QShader::description()}{QShader}, or, what is often more convenient, run
|
||||
the \c qsb tool on the \c{.qsb} file with the \c{-d} argument to inspect
|
||||
the metadata in human-readable form. The printed information includes,
|
||||
among other things, the uniform block member offsets, sizes, and the total
|
||||
size in bytes of each uniform block.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp render-init-1
|
||||
|
||||
The vertex and fragment shaders both need a uniform buffer at binding point
|
||||
0. This is ensured by the QRhiShaderResourceBindings object. The graphics
|
||||
pipeline is then setup with the shaders and a number of additional
|
||||
information. The example also relies on a number of convenient defaults,
|
||||
e.g. the primitive topology is
|
||||
\l{QRhiGraphicsPipeline::Triangles}{Triangles}, but that is the default,
|
||||
and therefore it is not explicitly set. See QRhiGraphicsPipeline for
|
||||
further details.
|
||||
|
||||
In addition to specifying the topology and various state, the pipeline must
|
||||
also be associated with:
|
||||
|
||||
\list
|
||||
|
||||
\li The vertex input layout in form of a QRhiVertexInputLayout. This
|
||||
specifies the type and component count for each vertex input location, the
|
||||
total stride in bytes per vertex, and other related data.
|
||||
QRhiVertexInputLayout only holds data, not actual native resources, and is
|
||||
copiable.
|
||||
|
||||
\li A valid and successfully initialized QRhiShaderResourceBindings object.
|
||||
This describes the layout of the resource bindings (uniform buffers,
|
||||
textures, samplers) the shaders expect. This must either by the
|
||||
QRhiShaderResourceBindings used when recording the draw calls, or another
|
||||
that is
|
||||
\l{QRhiShaderResourceBindings::isLayoutCompatible()}{layout-compatible with it}.
|
||||
This simple application takes the former approach.
|
||||
|
||||
\li A valid QRhiRenderPassDescriptor object. This must be retrieved from,
|
||||
or \l{QRhiRenderPassDescriptor::isCompatible()}{be compatible with} the
|
||||
render target. The example uses the former, by creating a
|
||||
QRhiRenderPassDescriptor object via
|
||||
QRhiSwapChain::newCompatibleRenderPassDescriptor().
|
||||
|
||||
\endlist
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp render-init-2
|
||||
|
||||
getShader() is a helper function that loads a \c{.qsb} file and
|
||||
deserializes a QShader from it.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp getshader
|
||||
|
||||
The \c{color.vert} shader specifies the following as the vertex inputs:
|
||||
|
||||
\badcode
|
||||
layout(location = 0) in vec4 position;
|
||||
layout(location = 1) in vec3 color;
|
||||
\endcode
|
||||
|
||||
The C++ code however provides vertex data as 2 floats for position, with 3
|
||||
floats for the color interleaved. (\c x, \c y, \c r, \c g, \c b for each
|
||||
vertex) This is why the stride is \c{5 * sizeof(float)} and the inputs for
|
||||
locations 0 and 1 are specified as \c Float2 and \c Float3, respectively.
|
||||
This is valid, and the \c z and \c w of the \c vec4 position will get set
|
||||
automatically.
|
||||
|
||||
\section1 Rendering
|
||||
|
||||
Recording a frame is started by calling \l{QRhi::beginFrame()} and finished
|
||||
by calling \l{QRhi::endFrame()}.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp beginframe
|
||||
|
||||
Some of the resources (buffers, textures) have static data in the
|
||||
application, meaning the content never changes. The vertex buffer's content
|
||||
is provided in the initialization step for example, and is not changed
|
||||
afterwards. These data update operations are recorded in \c
|
||||
m_initialUpdates. When not yet done, the commands on this resource update
|
||||
batch are merged into the per-frame batch.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp render-1
|
||||
|
||||
Having a per-frame resource update batch is necessary since the uniform
|
||||
buffer contents with the modelview-projection matrix and the opacity
|
||||
changes on every frame.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp render-rotation
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp render-opacity
|
||||
|
||||
To begin recording the render pass, a QRhiCommandBuffer is queried, and the
|
||||
output size is determined, which will be useful for setting up the viewport
|
||||
and resizing our fullscreen texture, if needed.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp render-cb
|
||||
|
||||
Starting a render pass implies clearing the render target's color and
|
||||
depth-stencil buffers (unless the render target flags indicate otherwise,
|
||||
but that is only an option for texture-based render targets). Here we
|
||||
specify black for color, 1.0f for depth, and 0 for stencil (unused). The
|
||||
last argument, \c resourceUpdates, is what ensures that the data update
|
||||
commands recorded on the batch get committed. Alternatively, we could have
|
||||
used QRhiCommandBuffer::resourceUpdate() instead. The render pass targets a
|
||||
swapchain, hence calling
|
||||
\l{QRhiSwapChain::currentFrameRenderTarget()}{currentFrameRenderTarget()}
|
||||
to get a valid QRhiRenderTarget.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp render-pass
|
||||
|
||||
Recording the draw call for the triangle is straightforward: set the
|
||||
pipeline, set the shader resources, set the vertex/index buffer(s), and
|
||||
record the draw call. Here we use a non-indexed draw with just 3 vertices.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp render-pass-record
|
||||
|
||||
The \l{QRhiCommandBuffer::setShaderResources()}{setShaderResources()} call
|
||||
has no arguments given, which implies using \c m_colorTriSrb since that was
|
||||
associated with the active QRhiGraphicsPipeline (\c m_colorPipeline).
|
||||
|
||||
We will not dive into the details of the rendering of the fullscreen
|
||||
background image. See the example source code for that. It is however worth
|
||||
noting a common pattern for "resizing" a texture or buffer resource. There
|
||||
is no such thing as changing the size of an existing native resource, so
|
||||
changing a texture or buffer size must be followed by a call to create(),
|
||||
to release and recreate the underlying native resources. To ensure that the
|
||||
QRhiTexture always has the required size, the application implements the
|
||||
following logic. Note that \c m_texture stays valid for the entire lifetime
|
||||
of the window, which means object references to it, e.g. in a
|
||||
QRhiShaderResourceBindings, continue to be valid all the time. It is only
|
||||
the underlying native resources that come and go over time.
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp ensure-texture
|
||||
|
||||
Once a QImage is generated and the QPainter-based drawing into it has
|
||||
finished, we use
|
||||
\l{QRhiResourceUpdateBatch::uploadTexture()}{uploadTexture()} to record a
|
||||
texture upload on the resource update batch:
|
||||
|
||||
\snippet rhiwindow/rhiwindow.cpp ensure-texture-2
|
||||
|
||||
\sa QRhi, QRhiSwapChain, QWindow, QRhiCommandBuffer, QRhiResourceUpdateBatch, QRhiBuffer, QRhiTexture
|
||||
*/
|
@ -4,4 +4,5 @@ TEMPLATE = subdirs
|
||||
QT_FOR_CONFIG += gui
|
||||
CONFIG += no_docs_target
|
||||
|
||||
SUBDIRS += rasterwindow
|
||||
SUBDIRS += rasterwindow \
|
||||
rhiwindow
|
||||
|
59
examples/gui/rhiwindow/CMakeLists.txt
Normal file
59
examples/gui/rhiwindow/CMakeLists.txt
Normal file
@ -0,0 +1,59 @@
|
||||
# Copyright (C) 2023 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(rhiwindow LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/gui/rhiwindow")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(rhiwindow
|
||||
main.cpp
|
||||
rhiwindow.cpp rhiwindow.h
|
||||
)
|
||||
|
||||
set_target_properties(rhiwindow PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(rhiwindow PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::GuiPrivate
|
||||
)
|
||||
|
||||
set_source_files_properties("shaders/prebuilt/color.vert.qsb"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "color.vert.qsb"
|
||||
)
|
||||
set_source_files_properties("shaders/prebuilt/color.frag.qsb"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "color.frag.qsb"
|
||||
)
|
||||
set_source_files_properties("shaders/prebuilt/quad.vert.qsb"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "quad.vert.qsb"
|
||||
)
|
||||
set_source_files_properties("shaders/prebuilt/quad.frag.qsb"
|
||||
PROPERTIES QT_RESOURCE_ALIAS "quad.frag.qsb"
|
||||
)
|
||||
qt_add_resources(rhiwindow "rhiwindow"
|
||||
PREFIX
|
||||
"/"
|
||||
FILES
|
||||
"shaders/prebuilt/color.vert.qsb"
|
||||
"shaders/prebuilt/color.frag.qsb"
|
||||
"shaders/prebuilt/quad.vert.qsb"
|
||||
"shaders/prebuilt/quad.frag.qsb"
|
||||
)
|
||||
|
||||
install(TARGETS rhiwindow
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
100
examples/gui/rhiwindow/main.cpp
Normal file
100
examples/gui/rhiwindow/main.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include <QGuiApplication>
|
||||
#include <QCommandLineParser>
|
||||
#include "rhiwindow.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
QRhi::Implementation graphicsApi;
|
||||
|
||||
// Use platform-specific defaults when no command-line arguments given.
|
||||
#if defined(Q_OS_WIN)
|
||||
graphicsApi = QRhi::D3D11;
|
||||
#elif defined(Q_OS_MACOS) || defined(Q_OS_IOS)
|
||||
graphicsApi = QRhi::Metal;
|
||||
#elif QT_CONFIG(vulkan)
|
||||
graphicsApi = QRhi::Vulkan;
|
||||
#else
|
||||
graphicsApi = QRhi::OpenGLES2;
|
||||
#endif
|
||||
|
||||
QCommandLineParser cmdLineParser;
|
||||
cmdLineParser.addHelpOption();
|
||||
QCommandLineOption nullOption({ "n", "null" }, QLatin1String("Null"));
|
||||
cmdLineParser.addOption(nullOption);
|
||||
QCommandLineOption glOption({ "g", "opengl" }, QLatin1String("OpenGL"));
|
||||
cmdLineParser.addOption(glOption);
|
||||
QCommandLineOption vkOption({ "v", "vulkan" }, QLatin1String("Vulkan"));
|
||||
cmdLineParser.addOption(vkOption);
|
||||
QCommandLineOption d3d11Option({ "d", "d3d11" }, QLatin1String("Direct3D 11"));
|
||||
cmdLineParser.addOption(d3d11Option);
|
||||
QCommandLineOption d3d12Option({ "D", "d3d12" }, QLatin1String("Direct3D 12"));
|
||||
cmdLineParser.addOption(d3d12Option);
|
||||
QCommandLineOption mtlOption({ "m", "metal" }, QLatin1String("Metal"));
|
||||
cmdLineParser.addOption(mtlOption);
|
||||
|
||||
cmdLineParser.process(app);
|
||||
if (cmdLineParser.isSet(nullOption))
|
||||
graphicsApi = QRhi::Null;
|
||||
if (cmdLineParser.isSet(glOption))
|
||||
graphicsApi = QRhi::OpenGLES2;
|
||||
if (cmdLineParser.isSet(vkOption))
|
||||
graphicsApi = QRhi::Vulkan;
|
||||
if (cmdLineParser.isSet(d3d11Option))
|
||||
graphicsApi = QRhi::D3D11;
|
||||
if (cmdLineParser.isSet(d3d12Option))
|
||||
graphicsApi = QRhi::D3D12;
|
||||
if (cmdLineParser.isSet(mtlOption))
|
||||
graphicsApi = QRhi::Metal;
|
||||
|
||||
//! [api-setup]
|
||||
// For OpenGL.
|
||||
QSurfaceFormat fmt;
|
||||
fmt.setDepthBufferSize(24);
|
||||
fmt.setStencilBufferSize(8);
|
||||
QSurfaceFormat::setDefaultFormat(fmt);
|
||||
|
||||
// For Vulkan.
|
||||
#if QT_CONFIG(vulkan)
|
||||
QVulkanInstance inst;
|
||||
if (graphicsApi == QRhi::Vulkan) {
|
||||
// Request validation, if available. This is completely optional
|
||||
// and has a performance impact, and should be avoided in production use.
|
||||
inst.setLayers({ "VK_LAYER_KHRONOS_validation" });
|
||||
// Play nice with QRhi.
|
||||
inst.setExtensions(QRhiVulkanInitParams::preferredInstanceExtensions());
|
||||
if (!inst.create()) {
|
||||
qWarning("Failed to create Vulkan instance, switching to OpenGL");
|
||||
graphicsApi = QRhi::OpenGLES2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//! [api-setup]
|
||||
|
||||
HelloWindow window(graphicsApi);
|
||||
|
||||
#if QT_CONFIG(vulkan)
|
||||
if (graphicsApi == QRhi::Vulkan)
|
||||
window.setVulkanInstance(&inst);
|
||||
#endif
|
||||
window.resize(1280, 720);
|
||||
window.setTitle(QCoreApplication::applicationName() + QLatin1String(" - ") + window.graphicsApiName());
|
||||
window.show();
|
||||
|
||||
int ret = app.exec();
|
||||
|
||||
// RhiWindow::event() will not get invoked when the
|
||||
// PlatformSurfaceAboutToBeDestroyed event is sent during the QWindow
|
||||
// destruction. That happens only when exiting via app::quit() instead of
|
||||
// the more common QWindow::close(). Take care of it: if the QPlatformWindow
|
||||
// is still around (there was no close() yet), get rid of the swapchain
|
||||
// while it's not too late.
|
||||
if (window.handle())
|
||||
window.releaseSwapChain();
|
||||
|
||||
return ret;
|
||||
}
|
435
examples/gui/rhiwindow/rhiwindow.cpp
Normal file
435
examples/gui/rhiwindow/rhiwindow.cpp
Normal file
@ -0,0 +1,435 @@
|
||||
// Copyright (C) 2020 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "rhiwindow.h"
|
||||
#include <QPlatformSurfaceEvent>
|
||||
#include <QPainter>
|
||||
#include <QFile>
|
||||
#include <rhi/qshader.h>
|
||||
|
||||
//! [rhiwindow-ctor]
|
||||
RhiWindow::RhiWindow(QRhi::Implementation graphicsApi)
|
||||
: m_graphicsApi(graphicsApi)
|
||||
{
|
||||
switch (graphicsApi) {
|
||||
case QRhi::OpenGLES2:
|
||||
setSurfaceType(OpenGLSurface);
|
||||
break;
|
||||
case QRhi::Vulkan:
|
||||
setSurfaceType(VulkanSurface);
|
||||
break;
|
||||
case QRhi::D3D11:
|
||||
case QRhi::D3D12:
|
||||
setSurfaceType(Direct3DSurface);
|
||||
break;
|
||||
case QRhi::Metal:
|
||||
setSurfaceType(MetalSurface);
|
||||
break;
|
||||
case QRhi::Null:
|
||||
break; // RasterSurface
|
||||
}
|
||||
}
|
||||
//! [rhiwindow-ctor]
|
||||
|
||||
QString RhiWindow::graphicsApiName() const
|
||||
{
|
||||
switch (m_graphicsApi) {
|
||||
case QRhi::Null:
|
||||
return QLatin1String("Null (no output)");
|
||||
case QRhi::OpenGLES2:
|
||||
return QLatin1String("OpenGL");
|
||||
case QRhi::Vulkan:
|
||||
return QLatin1String("Vulkan");
|
||||
case QRhi::D3D11:
|
||||
return QLatin1String("Direct3D 11");
|
||||
case QRhi::D3D12:
|
||||
return QLatin1String("Direct3D 12");
|
||||
case QRhi::Metal:
|
||||
return QLatin1String("Metal");
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
//! [expose]
|
||||
void RhiWindow::exposeEvent(QExposeEvent *)
|
||||
{
|
||||
// initialize and start rendering when the window becomes usable for graphics purposes
|
||||
if (isExposed() && !m_initialized) {
|
||||
init();
|
||||
resizeSwapChain();
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
const QSize surfaceSize = m_hasSwapChain ? m_sc->surfacePixelSize() : QSize();
|
||||
|
||||
// stop pushing frames when not exposed (or size is 0)
|
||||
if ((!isExposed() || (m_hasSwapChain && surfaceSize.isEmpty())) && m_initialized && !m_notExposed)
|
||||
m_notExposed = true;
|
||||
|
||||
// Continue when exposed again and the surface has a valid size. Note that
|
||||
// surfaceSize can be (0, 0) even though size() reports a valid one, hence
|
||||
// trusting surfacePixelSize() and not QWindow.
|
||||
if (isExposed() && m_initialized && m_notExposed && !surfaceSize.isEmpty()) {
|
||||
m_notExposed = false;
|
||||
m_newlyExposed = true;
|
||||
}
|
||||
|
||||
// always render a frame on exposeEvent() (when exposed) in order to update
|
||||
// immediately on window resize.
|
||||
if (isExposed() && !surfaceSize.isEmpty())
|
||||
render();
|
||||
}
|
||||
//! [expose]
|
||||
|
||||
//! [event]
|
||||
bool RhiWindow::event(QEvent *e)
|
||||
{
|
||||
switch (e->type()) {
|
||||
case QEvent::UpdateRequest:
|
||||
render();
|
||||
break;
|
||||
|
||||
case QEvent::PlatformSurface:
|
||||
// this is the proper time to tear down the swapchain (while the native window and surface are still around)
|
||||
if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
|
||||
releaseSwapChain();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QWindow::event(e);
|
||||
}
|
||||
//! [event]
|
||||
|
||||
//! [rhi-init]
|
||||
void RhiWindow::init()
|
||||
{
|
||||
if (m_graphicsApi == QRhi::Null) {
|
||||
QRhiNullInitParams params;
|
||||
m_rhi.reset(QRhi::create(QRhi::Null, ¶ms));
|
||||
}
|
||||
|
||||
#if QT_CONFIG(opengl)
|
||||
if (m_graphicsApi == QRhi::OpenGLES2) {
|
||||
m_fallbackSurface.reset(QRhiGles2InitParams::newFallbackSurface());
|
||||
QRhiGles2InitParams params;
|
||||
params.fallbackSurface = m_fallbackSurface.get();
|
||||
params.window = this;
|
||||
m_rhi.reset(QRhi::create(QRhi::OpenGLES2, ¶ms));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(vulkan)
|
||||
if (m_graphicsApi == QRhi::Vulkan) {
|
||||
QRhiVulkanInitParams params;
|
||||
params.inst = vulkanInstance();
|
||||
params.window = this;
|
||||
m_rhi.reset(QRhi::create(QRhi::Vulkan, ¶ms));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
if (m_graphicsApi == QRhi::D3D11) {
|
||||
QRhiD3D11InitParams params;
|
||||
// Enable the debug layer, if available. This is optional
|
||||
// and should be avoided in production builds.
|
||||
params.enableDebugLayer = true;
|
||||
m_rhi.reset(QRhi::create(QRhi::D3D11, ¶ms));
|
||||
} else if (m_graphicsApi == QRhi::D3D12) {
|
||||
QRhiD3D12InitParams params;
|
||||
// Enable the debug layer, if available. This is optional
|
||||
// and should be avoided in production builds.
|
||||
params.enableDebugLayer = true;
|
||||
m_rhi.reset(QRhi::create(QRhi::D3D12, ¶ms));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
|
||||
if (m_graphicsApi == QRhi::Metal) {
|
||||
QRhiMetalInitParams params;
|
||||
m_rhi.reset(QRhi::create(QRhi::Metal, ¶ms));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!m_rhi)
|
||||
qFatal("Failed to create RHI backend");
|
||||
//! [rhi-init]
|
||||
|
||||
//! [swapchain-init]
|
||||
m_sc.reset(m_rhi->newSwapChain());
|
||||
m_ds.reset(m_rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil,
|
||||
QSize(), // no need to set the size here, due to UsedWithSwapChainOnly
|
||||
1,
|
||||
QRhiRenderBuffer::UsedWithSwapChainOnly));
|
||||
m_sc->setWindow(this);
|
||||
m_sc->setDepthStencil(m_ds.get());
|
||||
m_rp.reset(m_sc->newCompatibleRenderPassDescriptor());
|
||||
m_sc->setRenderPassDescriptor(m_rp.get());
|
||||
//! [swapchain-init]
|
||||
|
||||
customInit();
|
||||
}
|
||||
|
||||
//! [swapchain-resize]
|
||||
void RhiWindow::resizeSwapChain()
|
||||
{
|
||||
m_hasSwapChain = m_sc->createOrResize(); // also handles m_ds
|
||||
|
||||
const QSize outputSize = m_sc->currentPixelSize();
|
||||
m_viewProjection = m_rhi->clipSpaceCorrMatrix();
|
||||
m_viewProjection.perspective(45.0f, outputSize.width() / (float) outputSize.height(), 0.01f, 1000.0f);
|
||||
m_viewProjection.translate(0, 0, -4);
|
||||
}
|
||||
//! [swapchain-resize]
|
||||
|
||||
void RhiWindow::releaseSwapChain()
|
||||
{
|
||||
if (m_hasSwapChain) {
|
||||
m_hasSwapChain = false;
|
||||
m_sc->destroy();
|
||||
}
|
||||
}
|
||||
|
||||
//! [render-precheck]
|
||||
void RhiWindow::render()
|
||||
{
|
||||
if (!m_hasSwapChain || m_notExposed)
|
||||
return;
|
||||
//! [render-precheck]
|
||||
|
||||
//! [render-resize]
|
||||
// If the window got resized or newly exposed, resize the swapchain. (the
|
||||
// newly-exposed case is not actually required by some platforms, but is
|
||||
// here for robustness and portability)
|
||||
//
|
||||
// This (exposeEvent + the logic here) is the only safe way to perform
|
||||
// resize handling. Note the usage of the RHI's surfacePixelSize(), and
|
||||
// never QWindow::size(). (the two may or may not be the same under the hood,
|
||||
// depending on the backend and platform)
|
||||
//
|
||||
if (m_sc->currentPixelSize() != m_sc->surfacePixelSize() || m_newlyExposed) {
|
||||
resizeSwapChain();
|
||||
if (!m_hasSwapChain)
|
||||
return;
|
||||
m_newlyExposed = false;
|
||||
}
|
||||
//! [render-resize]
|
||||
|
||||
//! [beginframe]
|
||||
QRhi::FrameOpResult result = m_rhi->beginFrame(m_sc.get());
|
||||
if (result == QRhi::FrameOpSwapChainOutOfDate) {
|
||||
resizeSwapChain();
|
||||
if (!m_hasSwapChain)
|
||||
return;
|
||||
result = m_rhi->beginFrame(m_sc.get());
|
||||
}
|
||||
if (result != QRhi::FrameOpSuccess) {
|
||||
qWarning("beginFrame failed with %d, will retry", result);
|
||||
requestUpdate();
|
||||
return;
|
||||
}
|
||||
|
||||
customRender();
|
||||
//! [beginframe]
|
||||
|
||||
//! [request-update]
|
||||
m_rhi->endFrame(m_sc.get());
|
||||
|
||||
// Always request the next frame via requestUpdate(). On some platforms this is backed
|
||||
// by a platform-specific solution, e.g. CVDisplayLink on macOS, which is potentially
|
||||
// more efficient than a timer, queued metacalls, etc.
|
||||
requestUpdate();
|
||||
}
|
||||
//! [request-update]
|
||||
|
||||
static float vertexData[] = {
|
||||
// Y up (note clipSpaceCorrMatrix in m_viewProjection), 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,
|
||||
};
|
||||
|
||||
//! [getshader]
|
||||
static QShader getShader(const QString &name)
|
||||
{
|
||||
QFile f(name);
|
||||
if (f.open(QIODevice::ReadOnly))
|
||||
return QShader::fromSerialized(f.readAll());
|
||||
|
||||
return QShader();
|
||||
}
|
||||
//! [getshader]
|
||||
|
||||
HelloWindow::HelloWindow(QRhi::Implementation graphicsApi)
|
||||
: RhiWindow(graphicsApi)
|
||||
{
|
||||
}
|
||||
|
||||
//! [ensure-texture]
|
||||
void HelloWindow::ensureFullscreenTexture(const QSize &pixelSize, QRhiResourceUpdateBatch *u)
|
||||
{
|
||||
if (m_texture && m_texture->pixelSize() == pixelSize)
|
||||
return;
|
||||
|
||||
if (!m_texture)
|
||||
m_texture.reset(m_rhi->newTexture(QRhiTexture::RGBA8, pixelSize));
|
||||
else
|
||||
m_texture->setPixelSize(pixelSize);
|
||||
|
||||
m_texture->create();
|
||||
|
||||
QImage image(pixelSize, QImage::Format_RGBA8888_Premultiplied);
|
||||
//! [ensure-texture]
|
||||
QPainter painter(&image);
|
||||
painter.fillRect(QRectF(QPointF(0, 0), pixelSize), QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f));
|
||||
painter.setPen(Qt::transparent);
|
||||
painter.setBrush({ QGradient(QGradient::DeepBlue) });
|
||||
painter.drawRoundedRect(QRectF(QPointF(20, 20), pixelSize - QSize(40, 40)), 16, 16);
|
||||
painter.setPen(Qt::black);
|
||||
QFont font;
|
||||
font.setPixelSize(0.05 * qMin(pixelSize.width(), pixelSize.height()));
|
||||
painter.setFont(font);
|
||||
painter.drawText(QRectF(QPointF(60, 60), pixelSize - QSize(120, 120)), 0,
|
||||
QLatin1String("Rendering with QRhi to a resizable QWindow.\nThe 3D API is %1.\nUse the command-line options to choose a different API.")
|
||||
.arg(graphicsApiName()));
|
||||
painter.end();
|
||||
|
||||
if (m_rhi->isYUpInNDC())
|
||||
image = image.mirrored();
|
||||
|
||||
//! [ensure-texture-2]
|
||||
u->uploadTexture(m_texture.get(), image);
|
||||
//! [ensure-texture-2]
|
||||
}
|
||||
|
||||
//! [render-init-1]
|
||||
void HelloWindow::customInit()
|
||||
{
|
||||
m_initialUpdates = m_rhi->nextResourceUpdateBatch();
|
||||
|
||||
m_vbuf.reset(m_rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData)));
|
||||
m_vbuf->create();
|
||||
m_initialUpdates->uploadStaticBuffer(m_vbuf.get(), vertexData);
|
||||
|
||||
static const quint32 UBUF_SIZE = 68;
|
||||
m_ubuf.reset(m_rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, UBUF_SIZE));
|
||||
m_ubuf->create();
|
||||
//! [render-init-1]
|
||||
|
||||
ensureFullscreenTexture(m_sc->surfacePixelSize(), m_initialUpdates);
|
||||
|
||||
m_sampler.reset(m_rhi->newSampler(QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
|
||||
QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge));
|
||||
m_sampler->create();
|
||||
|
||||
//! [render-init-2]
|
||||
m_colorTriSrb.reset(m_rhi->newShaderResourceBindings());
|
||||
static const QRhiShaderResourceBinding::StageFlags visibility =
|
||||
QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage;
|
||||
m_colorTriSrb->setBindings({
|
||||
QRhiShaderResourceBinding::uniformBuffer(0, visibility, m_ubuf.get())
|
||||
});
|
||||
m_colorTriSrb->create();
|
||||
|
||||
m_colorPipeline.reset(m_rhi->newGraphicsPipeline());
|
||||
// Enable depth testing; not quite needed for a simple triangle, but we
|
||||
// have a depth-stencil buffer so why not.
|
||||
m_colorPipeline->setDepthTest(true);
|
||||
m_colorPipeline->setDepthWrite(true);
|
||||
// Blend factors default to One, OneOneMinusSrcAlpha, which is convenient.
|
||||
QRhiGraphicsPipeline::TargetBlend premulAlphaBlend;
|
||||
premulAlphaBlend.enable = true;
|
||||
m_colorPipeline->setTargetBlends({ premulAlphaBlend });
|
||||
m_colorPipeline->setShaderStages({
|
||||
{ QRhiShaderStage::Vertex, getShader(QLatin1String(":/color.vert.qsb")) },
|
||||
{ QRhiShaderStage::Fragment, getShader(QLatin1String(":/color.frag.qsb")) }
|
||||
});
|
||||
QRhiVertexInputLayout inputLayout;
|
||||
inputLayout.setBindings({
|
||||
{ 5 * sizeof(float) }
|
||||
});
|
||||
inputLayout.setAttributes({
|
||||
{ 0, 0, QRhiVertexInputAttribute::Float2, 0 },
|
||||
{ 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
|
||||
});
|
||||
m_colorPipeline->setVertexInputLayout(inputLayout);
|
||||
m_colorPipeline->setShaderResourceBindings(m_colorTriSrb.get());
|
||||
m_colorPipeline->setRenderPassDescriptor(m_rp.get());
|
||||
m_colorPipeline->create();
|
||||
//! [render-init-2]
|
||||
|
||||
m_fullscreenQuadSrb.reset(m_rhi->newShaderResourceBindings());
|
||||
m_fullscreenQuadSrb->setBindings({
|
||||
QRhiShaderResourceBinding::sampledTexture(0, QRhiShaderResourceBinding::FragmentStage,
|
||||
m_texture.get(), m_sampler.get())
|
||||
});
|
||||
m_fullscreenQuadSrb->create();
|
||||
|
||||
m_fullscreenQuadPipeline.reset(m_rhi->newGraphicsPipeline());
|
||||
m_fullscreenQuadPipeline->setShaderStages({
|
||||
{ QRhiShaderStage::Vertex, getShader(QLatin1String(":/quad.vert.qsb")) },
|
||||
{ QRhiShaderStage::Fragment, getShader(QLatin1String(":/quad.frag.qsb")) }
|
||||
});
|
||||
m_fullscreenQuadPipeline->setVertexInputLayout({});
|
||||
m_fullscreenQuadPipeline->setShaderResourceBindings(m_fullscreenQuadSrb.get());
|
||||
m_fullscreenQuadPipeline->setRenderPassDescriptor(m_rp.get());
|
||||
m_fullscreenQuadPipeline->create();
|
||||
}
|
||||
|
||||
//! [render-1]
|
||||
void HelloWindow::customRender()
|
||||
{
|
||||
QRhiResourceUpdateBatch *resourceUpdates = m_rhi->nextResourceUpdateBatch();
|
||||
|
||||
if (m_initialUpdates) {
|
||||
resourceUpdates->merge(m_initialUpdates);
|
||||
m_initialUpdates->release();
|
||||
m_initialUpdates = nullptr;
|
||||
}
|
||||
//! [render-1]
|
||||
|
||||
//! [render-rotation]
|
||||
m_rotation += 1.0f;
|
||||
QMatrix4x4 modelViewProjection = m_viewProjection;
|
||||
modelViewProjection.rotate(m_rotation, 0, 1, 0);
|
||||
resourceUpdates->updateDynamicBuffer(m_ubuf.get(), 0, 64, modelViewProjection.constData());
|
||||
//! [render-rotation]
|
||||
|
||||
//! [render-opacity]
|
||||
m_opacity += m_opacityDir * 0.005f;
|
||||
if (m_opacity < 0.0f || m_opacity > 1.0f) {
|
||||
m_opacityDir *= -1;
|
||||
m_opacity = qBound(0.0f, m_opacity, 1.0f);
|
||||
}
|
||||
resourceUpdates->updateDynamicBuffer(m_ubuf.get(), 64, 4, &m_opacity);
|
||||
//! [render-opacity]
|
||||
|
||||
//! [render-cb]
|
||||
QRhiCommandBuffer *cb = m_sc->currentFrameCommandBuffer();
|
||||
const QSize outputSizeInPixels = m_sc->currentPixelSize();
|
||||
//! [render-cb]
|
||||
|
||||
// (re)create the texture with a size matching the output surface size, when necessary.
|
||||
ensureFullscreenTexture(outputSizeInPixels, resourceUpdates);
|
||||
|
||||
//! [render-pass]
|
||||
cb->beginPass(m_sc->currentFrameRenderTarget(), Qt::black, { 1.0f, 0 }, resourceUpdates);
|
||||
//! [render-pass]
|
||||
|
||||
cb->setGraphicsPipeline(m_fullscreenQuadPipeline.get());
|
||||
cb->setViewport({ 0, 0, float(outputSizeInPixels.width()), float(outputSizeInPixels.height()) });
|
||||
cb->setShaderResources();
|
||||
cb->draw(3);
|
||||
|
||||
//! [render-pass-record]
|
||||
cb->setGraphicsPipeline(m_colorPipeline.get());
|
||||
cb->setShaderResources();
|
||||
const QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf.get(), 0);
|
||||
cb->setVertexInput(0, 1, &vbufBinding);
|
||||
cb->draw(3);
|
||||
|
||||
cb->endPass();
|
||||
//! [render-pass-record]
|
||||
}
|
78
examples/gui/rhiwindow/rhiwindow.h
Normal file
78
examples/gui/rhiwindow/rhiwindow.h
Normal file
@ -0,0 +1,78 @@
|
||||
// Copyright (C) 2020 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef WINDOW_H
|
||||
#define WINDOW_H
|
||||
|
||||
#include <QWindow>
|
||||
#include <QOffscreenSurface>
|
||||
#include <rhi/qrhi.h>
|
||||
|
||||
class RhiWindow : public QWindow
|
||||
{
|
||||
public:
|
||||
RhiWindow(QRhi::Implementation graphicsApi);
|
||||
QString graphicsApiName() const;
|
||||
void releaseSwapChain();
|
||||
|
||||
protected:
|
||||
virtual void customInit() = 0;
|
||||
virtual void customRender() = 0;
|
||||
|
||||
// destruction order matters to a certain degree: the fallbackSurface must
|
||||
// outlive the rhi, the rhi must outlive all other resources. The resources
|
||||
// need no special order when destroying.
|
||||
#if QT_CONFIG(opengl)
|
||||
std::unique_ptr<QOffscreenSurface> m_fallbackSurface;
|
||||
#endif
|
||||
std::unique_ptr<QRhi> m_rhi;
|
||||
//! [swapchain-data]
|
||||
std::unique_ptr<QRhiSwapChain> m_sc;
|
||||
std::unique_ptr<QRhiRenderBuffer> m_ds;
|
||||
std::unique_ptr<QRhiRenderPassDescriptor> m_rp;
|
||||
//! [swapchain-data]
|
||||
bool m_hasSwapChain = false;
|
||||
QMatrix4x4 m_viewProjection;
|
||||
|
||||
private:
|
||||
void init();
|
||||
void resizeSwapChain();
|
||||
void render();
|
||||
|
||||
void exposeEvent(QExposeEvent *) override;
|
||||
bool event(QEvent *) override;
|
||||
|
||||
QRhi::Implementation m_graphicsApi;
|
||||
bool m_initialized = false;
|
||||
bool m_notExposed = false;
|
||||
bool m_newlyExposed = false;
|
||||
};
|
||||
|
||||
class HelloWindow : public RhiWindow
|
||||
{
|
||||
public:
|
||||
HelloWindow(QRhi::Implementation graphicsApi);
|
||||
|
||||
void customInit() override;
|
||||
void customRender() override;
|
||||
|
||||
private:
|
||||
void ensureFullscreenTexture(const QSize &pixelSize, QRhiResourceUpdateBatch *u);
|
||||
|
||||
std::unique_ptr<QRhiBuffer> m_vbuf;
|
||||
std::unique_ptr<QRhiBuffer> m_ubuf;
|
||||
std::unique_ptr<QRhiTexture> m_texture;
|
||||
std::unique_ptr<QRhiSampler> m_sampler;
|
||||
std::unique_ptr<QRhiShaderResourceBindings> m_colorTriSrb;
|
||||
std::unique_ptr<QRhiGraphicsPipeline> m_colorPipeline;
|
||||
std::unique_ptr<QRhiShaderResourceBindings> m_fullscreenQuadSrb;
|
||||
std::unique_ptr<QRhiGraphicsPipeline> m_fullscreenQuadPipeline;
|
||||
|
||||
QRhiResourceUpdateBatch *m_initialUpdates = nullptr;
|
||||
|
||||
float m_rotation = 0;
|
||||
float m_opacity = 1;
|
||||
int m_opacityDir = -1;
|
||||
};
|
||||
|
||||
#endif
|
4
examples/gui/rhiwindow/rhiwindow.pri
Normal file
4
examples/gui/rhiwindow/rhiwindow.pri
Normal file
@ -0,0 +1,4 @@
|
||||
INCLUDEPATH += $$PWD
|
||||
SOURCES += $$PWD/rhiwindow.cpp
|
||||
HEADERS += $$PWD/rhiwindow.h
|
||||
RESOURCES += $$PWD/rhiwindow.qrc
|
9
examples/gui/rhiwindow/rhiwindow.pro
Normal file
9
examples/gui/rhiwindow/rhiwindow.pro
Normal file
@ -0,0 +1,9 @@
|
||||
include(rhiwindow.pri)
|
||||
|
||||
QT += gui-private
|
||||
|
||||
SOURCES += \
|
||||
main.cpp
|
||||
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/gui/rhiwindow
|
||||
INSTALLS += target
|
8
examples/gui/rhiwindow/rhiwindow.qrc
Normal file
8
examples/gui/rhiwindow/rhiwindow.qrc
Normal file
@ -0,0 +1,8 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file alias="color.vert.qsb">shaders/prebuilt/color.vert.qsb</file>
|
||||
<file alias="color.frag.qsb">shaders/prebuilt/color.frag.qsb</file>
|
||||
<file alias="quad.vert.qsb">shaders/prebuilt/quad.vert.qsb</file>
|
||||
<file alias="quad.frag.qsb">shaders/prebuilt/quad.frag.qsb</file>
|
||||
</qresource>
|
||||
</RCC>
|
15
examples/gui/rhiwindow/shaders/color.frag
Normal file
15
examples/gui/rhiwindow/shaders/color.frag
Normal file
@ -0,0 +1,15 @@
|
||||
#version 440
|
||||
|
||||
layout(location = 0) in vec3 v_color;
|
||||
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 mvp;
|
||||
float opacity;
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
fragColor = vec4(v_color * opacity, opacity);
|
||||
}
|
17
examples/gui/rhiwindow/shaders/color.vert
Normal file
17
examples/gui/rhiwindow/shaders/color.vert
Normal file
@ -0,0 +1,17 @@
|
||||
#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;
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
v_color = color;
|
||||
gl_Position = mvp * position;
|
||||
}
|
BIN
examples/gui/rhiwindow/shaders/prebuilt/color.frag.qsb
Normal file
BIN
examples/gui/rhiwindow/shaders/prebuilt/color.frag.qsb
Normal file
Binary file not shown.
BIN
examples/gui/rhiwindow/shaders/prebuilt/color.vert.qsb
Normal file
BIN
examples/gui/rhiwindow/shaders/prebuilt/color.vert.qsb
Normal file
Binary file not shown.
BIN
examples/gui/rhiwindow/shaders/prebuilt/quad.frag.qsb
Normal file
BIN
examples/gui/rhiwindow/shaders/prebuilt/quad.frag.qsb
Normal file
Binary file not shown.
BIN
examples/gui/rhiwindow/shaders/prebuilt/quad.vert.qsb
Normal file
BIN
examples/gui/rhiwindow/shaders/prebuilt/quad.vert.qsb
Normal file
Binary file not shown.
11
examples/gui/rhiwindow/shaders/quad.frag
Normal file
11
examples/gui/rhiwindow/shaders/quad.frag
Normal file
@ -0,0 +1,11 @@
|
||||
#version 440
|
||||
|
||||
layout(location = 0) in vec2 v_uv;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
layout(binding = 0) uniform sampler2D tex;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 c = texture(tex, v_uv);
|
||||
fragColor = vec4(c.rgb * c.a, c.a);
|
||||
}
|
10
examples/gui/rhiwindow/shaders/quad.vert
Normal file
10
examples/gui/rhiwindow/shaders/quad.vert
Normal file
@ -0,0 +1,10 @@
|
||||
#version 440
|
||||
|
||||
layout (location = 0) out vec2 v_uv;
|
||||
|
||||
void main()
|
||||
{
|
||||
// https://www.saschawillems.de/blog/2016/08/13/vulkan-tutorial-on-rendering-a-fullscreen-quad-without-buffers/
|
||||
v_uv = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
|
||||
gl_Position = vec4(v_uv * 2.0 - 1.0, 0.0, 1.0);
|
||||
}
|
@ -212,14 +212,10 @@ qt_internal_add_module(Gui
|
||||
painting/qtriangulatingstroker.cpp painting/qtriangulatingstroker_p.h
|
||||
painting/qtriangulator.cpp painting/qtriangulator_p.h
|
||||
painting/qvectorpath_p.h
|
||||
rhi/qrhi.cpp rhi/qrhi_p.h
|
||||
rhi/qrhi_p_p.h
|
||||
rhi/qrhi.cpp rhi/qrhi.h rhi/qrhi_platform.h rhi/qrhi_p.h
|
||||
rhi/qrhinull.cpp rhi/qrhinull_p.h
|
||||
rhi/qrhinull_p_p.h
|
||||
rhi/qshader.cpp rhi/qshader_p.h
|
||||
rhi/qshader_p_p.h
|
||||
rhi/qshaderdescription.cpp rhi/qshaderdescription_p.h
|
||||
rhi/qshaderdescription_p_p.h
|
||||
rhi/qshader.cpp rhi/qshader.h rhi/qshader_p.h
|
||||
rhi/qshaderdescription.cpp rhi/qshaderdescription.h rhi/qshaderdescription_p.h
|
||||
text/qabstracttextdocumentlayout.cpp text/qabstracttextdocumentlayout.h text/qabstracttextdocumentlayout_p.h
|
||||
text/qdistancefield.cpp text/qdistancefield_p.h
|
||||
text/qfont.cpp text/qfont.h text/qfont_p.h
|
||||
@ -283,6 +279,8 @@ qt_internal_add_module(Gui
|
||||
GENERATE_CPP_EXPORTS
|
||||
QPA_HEADER_FILTERS
|
||||
"(^|/)qplatform.+\\.h$|(^|/)qwindowsystem.+\\.h$"
|
||||
RHI_HEADER_FILTERS
|
||||
"(^|/)qrhi\\.h$|(^|/)qrhi_platform\\.h$|(^|/)qshader\\.h$|(^|/)qshaderdescription\\.h$"
|
||||
)
|
||||
|
||||
# Resources:
|
||||
@ -358,7 +356,6 @@ qt_internal_extend_target(Gui CONDITION QT_FEATURE_opengl
|
||||
opengl/qopenglfunctions.cpp
|
||||
opengl/qopenglprogrambinarycache.cpp opengl/qopenglprogrambinarycache_p.h
|
||||
rhi/qrhigles2.cpp rhi/qrhigles2_p.h
|
||||
rhi/qrhigles2_p_p.h
|
||||
)
|
||||
|
||||
qt_internal_extend_target(Gui CONDITION MACOS
|
||||
@ -409,10 +406,8 @@ qt_internal_extend_target(Gui CONDITION WIN32
|
||||
platform/windows/qwindowsmimeconverter.h platform/windows/qwindowsmimeconverter.cpp
|
||||
platform/windows/qwindowsnativeinterface.cpp
|
||||
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
|
||||
@ -832,8 +827,7 @@ qt_internal_extend_target(Gui CONDITION QT_FEATURE_filesystemmodel
|
||||
|
||||
qt_internal_extend_target(Gui CONDITION QT_FEATURE_vulkan
|
||||
SOURCES
|
||||
rhi/qrhivulkan.cpp rhi/qrhivulkan_p.h
|
||||
rhi/qrhivulkanext_p.h
|
||||
rhi/qrhivulkan.cpp rhi/qrhivulkan_p.h rhi/qrhivulkanext_p.h
|
||||
vulkan/qbasicvulkanplatforminstance.cpp vulkan/qbasicvulkanplatforminstance_p.h
|
||||
vulkan/qplatformvulkaninstance.cpp vulkan/qplatformvulkaninstance.h
|
||||
vulkan/qvulkandefaultinstance.cpp vulkan/qvulkandefaultinstance_p.h
|
||||
@ -969,7 +963,6 @@ qt_internal_extend_target(Gui CONDITION QT_FEATURE_xkbcommon AND UNIX
|
||||
qt_internal_extend_target(Gui CONDITION IOS OR MACOS
|
||||
SOURCES
|
||||
rhi/qrhimetal.mm rhi/qrhimetal_p.h
|
||||
rhi/qrhimetal_p_p.h
|
||||
PUBLIC_LIBRARIES
|
||||
${FWMetal}
|
||||
)
|
||||
|
@ -16,3 +16,8 @@
|
||||
#include <QtGui/qpa/qplatformscreen_p.h>
|
||||
#include <QtGui/private/qguiapplication_p.h>
|
||||
#include <QtGui/private/qkeymapper_p.h>
|
||||
|
||||
// rhi
|
||||
#include <QtGui/rhi/qrhi.h>
|
||||
#include <QtGui/rhi/qshader.h>
|
||||
#include <QtGui/rhi/qshaderdescription.h>
|
||||
|
16
src/gui/doc/snippets/rhioffscreen/color.frag
Normal file
16
src/gui/doc/snippets/rhioffscreen/color.frag
Normal file
@ -0,0 +1,16 @@
|
||||
//! [0]
|
||||
#version 440
|
||||
|
||||
layout(location = 0) in vec3 v_color;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 mvp;
|
||||
float opacity;
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
fragColor = vec4(v_color * opacity, opacity);
|
||||
}
|
||||
//! [0]
|
18
src/gui/doc/snippets/rhioffscreen/color.vert
Normal file
18
src/gui/doc/snippets/rhioffscreen/color.vert
Normal file
@ -0,0 +1,18 @@
|
||||
//! [0]
|
||||
#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;
|
||||
};
|
||||
|
||||
void main()
|
||||
{
|
||||
v_color = color;
|
||||
gl_Position = mvp * position;
|
||||
}
|
||||
//! [0]
|
151
src/gui/doc/snippets/rhioffscreen/main.cpp
Normal file
151
src/gui/doc/snippets/rhioffscreen/main.cpp
Normal file
@ -0,0 +1,151 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
//! [0]
|
||||
#include <QGuiApplication>
|
||||
#include <QImage>
|
||||
#include <QFile>
|
||||
#include <rhi/qrhi.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
std::unique_ptr<QRhi> rhi;
|
||||
#if defined(Q_OS_WIN)
|
||||
QRhiD3D12InitParams params;
|
||||
rhi.reset(QRhi::create(QRhi::D3D12, ¶ms));
|
||||
#elif defined(Q_OS_MACOS) || defined(Q_OS_IOS)
|
||||
QRhiMetalInitParams params;
|
||||
rhi.reset(QRhi::create(QRhi::Metal, ¶ms));
|
||||
#elif QT_CONFIG(vulkan)
|
||||
QVulkanInstance inst;
|
||||
inst.setExtensions(QRhiVulkanInitParams::preferredInstanceExtensions());
|
||||
if (inst.create()) {
|
||||
QRhiVulkanInitParams params;
|
||||
params.inst = &inst;
|
||||
rhi.reset(QRhi::create(QRhi::Vulkan, ¶ms));
|
||||
} else {
|
||||
qFatal("Failed to create Vulkan instance");
|
||||
}
|
||||
#endif
|
||||
if (rhi)
|
||||
qDebug() << rhi->backendName() << rhi->driverInfo();
|
||||
else
|
||||
qFatal("Failed to initialize RHI");
|
||||
|
||||
float rotation = 0.0f;
|
||||
float opacity = 1.0f;
|
||||
int opacityDir = 1;
|
||||
|
||||
std::unique_ptr<QRhiTexture> tex(rhi->newTexture(QRhiTexture::RGBA8,
|
||||
QSize(1280, 720),
|
||||
1,
|
||||
QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource));
|
||||
tex->create();
|
||||
std::unique_ptr<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget({ tex.get() }));
|
||||
std::unique_ptr<QRhiRenderPassDescriptor> rp(rt->newCompatibleRenderPassDescriptor());
|
||||
rt->setRenderPassDescriptor(rp.get());
|
||||
rt->create();
|
||||
|
||||
QMatrix4x4 viewProjection = rhi->clipSpaceCorrMatrix();
|
||||
viewProjection.perspective(45.0f, 1280 / 720.f, 0.01f, 1000.0f);
|
||||
viewProjection.translate(0, 0, -4);
|
||||
|
||||
static float vertexData[] = { // 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,
|
||||
};
|
||||
|
||||
std::unique_ptr<QRhiBuffer> vbuf(rhi->newBuffer(QRhiBuffer::Immutable,
|
||||
QRhiBuffer::VertexBuffer,
|
||||
sizeof(vertexData)));
|
||||
vbuf->create();
|
||||
|
||||
std::unique_ptr<QRhiBuffer> ubuf(rhi->newBuffer(QRhiBuffer::Dynamic,
|
||||
QRhiBuffer::UniformBuffer,
|
||||
64 + 4));
|
||||
ubuf->create();
|
||||
|
||||
std::unique_ptr<QRhiShaderResourceBindings> srb(rhi->newShaderResourceBindings());
|
||||
srb->setBindings({
|
||||
QRhiShaderResourceBinding::uniformBuffer(0,
|
||||
QRhiShaderResourceBinding::VertexStage | QRhiShaderResourceBinding::FragmentStage,
|
||||
ubuf.get())
|
||||
});
|
||||
srb->create();
|
||||
|
||||
std::unique_ptr<QRhiGraphicsPipeline> ps(rhi->newGraphicsPipeline());
|
||||
QRhiGraphicsPipeline::TargetBlend premulAlphaBlend;
|
||||
premulAlphaBlend.enable = true;
|
||||
ps->setTargetBlends({ premulAlphaBlend });
|
||||
static auto getShader = [](const QString &name) {
|
||||
QFile f(name);
|
||||
if (f.open(QIODevice::ReadOnly))
|
||||
return QShader::fromSerialized(f.readAll());
|
||||
return QShader();
|
||||
};
|
||||
ps->setShaderStages({
|
||||
{ QRhiShaderStage::Vertex, getShader(QLatin1String("color.vert.qsb")) },
|
||||
{ QRhiShaderStage::Fragment, getShader(QLatin1String("color.frag.qsb")) }
|
||||
});
|
||||
QRhiVertexInputLayout inputLayout;
|
||||
inputLayout.setBindings({
|
||||
{ 5 * sizeof(float) }
|
||||
});
|
||||
inputLayout.setAttributes({
|
||||
{ 0, 0, QRhiVertexInputAttribute::Float2, 0 },
|
||||
{ 0, 1, QRhiVertexInputAttribute::Float3, 2 * sizeof(float) }
|
||||
});
|
||||
ps->setVertexInputLayout(inputLayout);
|
||||
ps->setShaderResourceBindings(srb.get());
|
||||
ps->setRenderPassDescriptor(rp.get());
|
||||
ps->create();
|
||||
|
||||
QRhiCommandBuffer *cb;
|
||||
for (int frame = 0; frame < 20; ++frame) {
|
||||
rhi->beginOffscreenFrame(&cb);
|
||||
|
||||
QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
|
||||
if (frame == 0)
|
||||
u->uploadStaticBuffer(vbuf.get(), vertexData);
|
||||
|
||||
QMatrix4x4 mvp = viewProjection;
|
||||
mvp.rotate(rotation, 0, 1, 0);
|
||||
u->updateDynamicBuffer(ubuf.get(), 0, 64, mvp.constData());
|
||||
rotation += 5.0f;
|
||||
|
||||
u->updateDynamicBuffer(ubuf.get(), 64, 4, &opacity);
|
||||
opacity += opacityDir * 0.2f;
|
||||
if (opacity < 0.0f || opacity > 1.0f) {
|
||||
opacityDir *= -1;
|
||||
opacity = qBound(0.0f, opacity, 1.0f);
|
||||
}
|
||||
|
||||
cb->beginPass(rt.get(), Qt::green, { 1.0f, 0 }, u);
|
||||
cb->setGraphicsPipeline(ps.get());
|
||||
cb->setViewport({ 0, 0, 1280, 720 });
|
||||
cb->setShaderResources();
|
||||
const QRhiCommandBuffer::VertexInput vbufBinding(vbuf.get(), 0);
|
||||
cb->setVertexInput(0, 1, &vbufBinding);
|
||||
cb->draw(3);
|
||||
QRhiReadbackResult readbackResult;
|
||||
u = rhi->nextResourceUpdateBatch();
|
||||
u->readBackTexture({ tex.get() }, &readbackResult);
|
||||
cb->endPass(u);
|
||||
|
||||
rhi->endOffscreenFrame();
|
||||
|
||||
QImage image(reinterpret_cast<const uchar *>(readbackResult.data.constData()),
|
||||
readbackResult.pixelSize.width(),
|
||||
readbackResult.pixelSize.height(),
|
||||
QImage::Format_RGBA8888_Premultiplied);
|
||||
if (rhi->isYUpInFramebuffer())
|
||||
image = image.mirrored();
|
||||
image.save(QString::asprintf("frame%d.png", frame));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
//! [0]
|
@ -51,6 +51,56 @@
|
||||
that prefer more low-level APIs to text and font handling can use classes
|
||||
like QRawFont and QGlyphRun.
|
||||
|
||||
\section1 RHI Graphics
|
||||
|
||||
The Qt Rendering Hardware Interface is an abstraction for hardware accelerated
|
||||
graphics APIs, such as, \l{https://www.khronos.org/opengl/}{OpenGL},
|
||||
\l{https://www.khronos.org/opengles/}{OpenGL ES},
|
||||
\l{https://docs.microsoft.com/en-us/windows/desktop/direct3d}{Direct3D},
|
||||
\l{https://developer.apple.com/metal/}{Metal}, and
|
||||
\l{https://www.khronos.org/vulkan/}{Vulkan}.
|
||||
|
||||
As an alternative to using OpenGL or Vulkan directly to render to a
|
||||
QWindow, \l QRhi and the related classes provide a portable, cross-platform
|
||||
3D graphics and compute API complemented by a shader conditioning and
|
||||
transpiling pipeline. This way applications can avoid directly depending on
|
||||
a single, and, in some cases, vendor or platform-specific 3D API.
|
||||
|
||||
Below is a list of the main RHI-related classes. These are complemented by
|
||||
a number of additional classes and structs.
|
||||
|
||||
\list
|
||||
\li QRhi
|
||||
\li QShader
|
||||
\li QShaderDescription
|
||||
\li QRhiCommandBuffer
|
||||
\li QRhiResourceUpdateBatch
|
||||
\li QRhiBuffer
|
||||
\li QRhiRenderBuffer
|
||||
\li QRhiTexture
|
||||
\li QRhiSampler
|
||||
\li QRhiTextureRenderTarget
|
||||
\li QRhiShaderResourceBindings
|
||||
\li QRhiGraphicsPipeline
|
||||
\li QRhiComputePipeline
|
||||
\li QRhiSwapChain
|
||||
\endlist
|
||||
|
||||
See the \l{RHI Window Example} for an introductory example of creating a
|
||||
portable, cross-platform application that performs accelerated 3D rendering
|
||||
onto a QWindow using QRhi.
|
||||
|
||||
\note The RHI family of APIs are currently offered with a limited
|
||||
compatibility guarantee, as opposed to regular Qt public APIs. See \l QRhi
|
||||
for details.
|
||||
|
||||
\section1 3D Matrix and Vector Math
|
||||
|
||||
The Qt GUI module also contains a few math classes to aid with the most
|
||||
common mathematical operations related to 3D graphics. These classes
|
||||
include \l {QMatrix4x4}, \l {QVector2D}, \l {QVector3D}, \l {QVector4D},
|
||||
and \l {QQuaternion}.
|
||||
|
||||
\section1 OpenGL and OpenGL ES Integration
|
||||
|
||||
QWindow supports rendering using OpenGL and OpenGL ES, depending on what the
|
||||
@ -86,10 +136,6 @@
|
||||
|
||||
For more information, see the \l {OpenGL Window Example}.
|
||||
|
||||
The Qt GUI module also contains a few math classes to aid with the most
|
||||
common mathematical operations related to 3D graphics. These classes include
|
||||
\l {QMatrix4x4}, \l {QVector4D}, and \l {QQuaternion}.
|
||||
|
||||
A \l {QWindow} created with the \l {QSurface::OpenGLSurface} can be used in
|
||||
combination with \l QPainter and \l QOpenGLPaintDevice to have OpenGL
|
||||
hardware-accelerated 2D graphics by sacrificing some of the visual quality.
|
||||
@ -104,18 +150,21 @@
|
||||
|
||||
On Android, Vulkan headers were added in API level 24 of the NDK.
|
||||
|
||||
Relevant classes:
|
||||
The main relevant classes for low-level Vulkan support are:
|
||||
|
||||
\list
|
||||
\li QVulkanDeviceFunctions
|
||||
\li QVulkanExtension
|
||||
\li QVulkanFunctions
|
||||
\li QVulkanInfoVector
|
||||
\li QVulkanInstance
|
||||
\li QVulkanWindow
|
||||
\li QVulkanWindowRenderer
|
||||
\li QVulkanFunctions
|
||||
\li QVulkanDeviceFunctions
|
||||
\endlist
|
||||
|
||||
In addition, \l QVulkanWindow provides a convenience subclass of QWindow
|
||||
that makes it easier to get started with implementing Vulkan-based
|
||||
rendering targeting a QWindow. Using this helper class is completely
|
||||
optional; applications with more advanced Vulkan-based renderers may
|
||||
instead want to use a QWindow with the \l {QSurface::VulkanSurface} type
|
||||
directly.
|
||||
|
||||
For more information, see the \l{Hello Vulkan Widget Example}
|
||||
and the \l {Hello Vulkan Triangle Example}.
|
||||
|
||||
|
@ -54,6 +54,8 @@
|
||||
\list
|
||||
\li \l {Application Windows} {Qt GUI Application Windows}
|
||||
\li \l {2D Graphics} {Qt GUI 2D Graphics}
|
||||
\li \l {RHI Graphics} {Qt GUI Accelerated 2D and 3D Graphics using the Qt RHI}
|
||||
\li \l {3D Matrix and Vector Math} {Qt GUI Matrix and Vector Math}
|
||||
\li \l {OpenGL and OpenGL ES Integration}
|
||||
{Qt GUI OpenGL and OpenGL ES Integration}
|
||||
\li \l {Vulkan Integration} {Qt GUI Vulkan Integration}
|
||||
|
@ -69,6 +69,7 @@ QOpenGLContext *qt_gl_global_share_context()
|
||||
|
||||
/*!
|
||||
\class QOpenGLContext
|
||||
\ingroup painting-3D
|
||||
\inmodule QtGui
|
||||
\since 5.0
|
||||
\brief The QOpenGLContext class represents a native OpenGL context, enabling
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <QtCore/qmutex.h>
|
||||
#include <QtCore/QLoggingCategory>
|
||||
#include <QtGui/private/qopenglcontext_p.h>
|
||||
#include <QtGui/private/qshader_p.h>
|
||||
#include <rhi/qshader.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
//
|
||||
|
||||
#include <qpa/qplatformbackingstore.h>
|
||||
#include <QtGui/private/qrhi_p.h>
|
||||
#include <rhi/qrhi.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
@ -8,20 +8,9 @@
|
||||
#if QT_CONFIG(opengl)
|
||||
#include <QtGui/qoffscreensurface.h>
|
||||
#include <QtGui/private/qopenglcontext_p.h>
|
||||
#include <QtGui/private/qrhigles2_p.h>
|
||||
#endif
|
||||
|
||||
#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)
|
||||
#include <QtGui/private/qrhimetal_p.h>
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(vulkan)
|
||||
#include <QtGui/private/qrhivulkan_p.h>
|
||||
#include <QtGui/private/qvulkandefaultinstance_p.h>
|
||||
#endif
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <QtGui/qwindow.h>
|
||||
#include <QtGui/qsurfaceformat.h>
|
||||
#include <QtGui/qoffscreensurface.h>
|
||||
#include <QtGui/private/qrhi_p.h>
|
||||
#include <rhi/qrhi.h>
|
||||
#include <qpa/qplatformbackingstore.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
3029
src/gui/rhi/qrhi.cpp
3029
src/gui/rhi/qrhi.cpp
File diff suppressed because it is too large
Load Diff
1974
src/gui/rhi/qrhi.h
Normal file
1974
src/gui/rhi/qrhi.h
Normal file
File diff suppressed because it is too large
Load Diff
2603
src/gui/rhi/qrhi_p.h
2603
src/gui/rhi/qrhi_p.h
File diff suppressed because it is too large
Load Diff
@ -1,804 +0,0 @@
|
||||
// Copyright (C) 2019 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QRHI_P_H
|
||||
#define QRHI_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "qrhi_p.h"
|
||||
#include <QBitArray>
|
||||
#include <QAtomicInt>
|
||||
#include <QElapsedTimer>
|
||||
#include <QLoggingCategory>
|
||||
#include <QtCore/qset.h>
|
||||
#include <QtCore/qvarlengtharray.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#define QRHI_RES(t, x) static_cast<t *>(x)
|
||||
#define QRHI_RES_RHI(t) t *rhiD = static_cast<t *>(m_rhi)
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(QRHI_LOG_INFO)
|
||||
|
||||
class QRhiImplementation
|
||||
{
|
||||
public:
|
||||
virtual ~QRhiImplementation();
|
||||
|
||||
virtual bool create(QRhi::Flags flags) = 0;
|
||||
virtual void destroy() = 0;
|
||||
|
||||
virtual QRhiGraphicsPipeline *createGraphicsPipeline() = 0;
|
||||
virtual QRhiComputePipeline *createComputePipeline() = 0;
|
||||
virtual QRhiShaderResourceBindings *createShaderResourceBindings() = 0;
|
||||
virtual QRhiBuffer *createBuffer(QRhiBuffer::Type type,
|
||||
QRhiBuffer::UsageFlags usage,
|
||||
quint32 size) = 0;
|
||||
virtual QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount,
|
||||
QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint) = 0;
|
||||
virtual QRhiTexture *createTexture(QRhiTexture::Format format,
|
||||
const QSize &pixelSize,
|
||||
int depth,
|
||||
int arraySize,
|
||||
int sampleCount,
|
||||
QRhiTexture::Flags flags) = 0;
|
||||
virtual QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
|
||||
QRhiSampler::Filter minFilter,
|
||||
QRhiSampler::Filter mipmapMode,
|
||||
QRhiSampler:: AddressMode u,
|
||||
QRhiSampler::AddressMode v,
|
||||
QRhiSampler::AddressMode w) = 0;
|
||||
|
||||
virtual QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
|
||||
QRhiTextureRenderTarget::Flags flags) = 0;
|
||||
|
||||
virtual QRhiSwapChain *createSwapChain() = 0;
|
||||
virtual QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) = 0;
|
||||
virtual QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) = 0;
|
||||
virtual QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) = 0;
|
||||
virtual QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) = 0;
|
||||
virtual QRhi::FrameOpResult finish() = 0;
|
||||
|
||||
virtual void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
|
||||
|
||||
virtual void beginPass(QRhiCommandBuffer *cb,
|
||||
QRhiRenderTarget *rt,
|
||||
const QColor &colorClearValue,
|
||||
const QRhiDepthStencilClearValue &depthStencilClearValue,
|
||||
QRhiResourceUpdateBatch *resourceUpdates,
|
||||
QRhiCommandBuffer::BeginPassFlags flags) = 0;
|
||||
virtual void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
|
||||
|
||||
virtual void setGraphicsPipeline(QRhiCommandBuffer *cb,
|
||||
QRhiGraphicsPipeline *ps) = 0;
|
||||
|
||||
virtual void setShaderResources(QRhiCommandBuffer *cb,
|
||||
QRhiShaderResourceBindings *srb,
|
||||
int dynamicOffsetCount,
|
||||
const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) = 0;
|
||||
|
||||
virtual void setVertexInput(QRhiCommandBuffer *cb,
|
||||
int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
|
||||
QRhiBuffer *indexBuf, quint32 indexOffset,
|
||||
QRhiCommandBuffer::IndexFormat indexFormat) = 0;
|
||||
|
||||
virtual void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) = 0;
|
||||
virtual void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) = 0;
|
||||
virtual void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) = 0;
|
||||
virtual void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) = 0;
|
||||
|
||||
virtual void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
|
||||
quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) = 0;
|
||||
virtual void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
|
||||
quint32 instanceCount, quint32 firstIndex,
|
||||
qint32 vertexOffset, quint32 firstInstance) = 0;
|
||||
|
||||
virtual void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) = 0;
|
||||
virtual void debugMarkEnd(QRhiCommandBuffer *cb) = 0;
|
||||
virtual void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) = 0;
|
||||
|
||||
virtual void beginComputePass(QRhiCommandBuffer *cb,
|
||||
QRhiResourceUpdateBatch *resourceUpdates,
|
||||
QRhiCommandBuffer::BeginPassFlags flags) = 0;
|
||||
virtual void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
|
||||
virtual void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) = 0;
|
||||
virtual void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) = 0;
|
||||
|
||||
virtual const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) = 0;
|
||||
virtual void beginExternal(QRhiCommandBuffer *cb) = 0;
|
||||
virtual void endExternal(QRhiCommandBuffer *cb) = 0;
|
||||
virtual double lastCompletedGpuTime(QRhiCommandBuffer *cb) = 0;
|
||||
|
||||
virtual QList<int> supportedSampleCounts() const = 0;
|
||||
virtual int ubufAlignment() const = 0;
|
||||
virtual bool isYUpInFramebuffer() const = 0;
|
||||
virtual bool isYUpInNDC() const = 0;
|
||||
virtual bool isClipDepthZeroToOne() const = 0;
|
||||
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 resourceLimit(QRhi::ResourceLimit limit) const = 0;
|
||||
virtual const QRhiNativeHandles *nativeHandles() = 0;
|
||||
virtual QRhiDriverInfo driverInfo() const = 0;
|
||||
virtual QRhiStats statistics() = 0;
|
||||
virtual bool makeThreadLocalNativeContextCurrent() = 0;
|
||||
virtual void releaseCachedResources() = 0;
|
||||
virtual bool isDeviceLost() const = 0;
|
||||
|
||||
virtual QByteArray pipelineCacheData() = 0;
|
||||
virtual void setPipelineCacheData(const QByteArray &data) = 0;
|
||||
|
||||
void prepareForCreate(QRhi *rhi, QRhi::Implementation impl, QRhi::Flags flags);
|
||||
|
||||
bool isCompressedFormat(QRhiTexture::Format format) const;
|
||||
void compressedFormatInfo(QRhiTexture::Format format, const QSize &size,
|
||||
quint32 *bpl, quint32 *byteSize,
|
||||
QSize *blockDim) const;
|
||||
void textureFormatInfo(QRhiTexture::Format format, const QSize &size,
|
||||
quint32 *bpl, quint32 *byteSize, quint32 *bytesPerPixel) const;
|
||||
|
||||
void registerResource(QRhiResource *res, bool ownsNativeResources = true)
|
||||
{
|
||||
// The ownsNativeResources is relevant for the (graphics resource) leak
|
||||
// check in ~QRhiImplementation; when false, the registration's sole
|
||||
// purpose is to automatically null out the resource's m_rhi pointer in
|
||||
// case the rhi goes away first. (which should not happen in
|
||||
// well-written applications but we try to be graceful)
|
||||
resources.insert(res, ownsNativeResources);
|
||||
}
|
||||
|
||||
void unregisterResource(QRhiResource *res)
|
||||
{
|
||||
resources.remove(res);
|
||||
}
|
||||
|
||||
void addDeleteLater(QRhiResource *res)
|
||||
{
|
||||
if (inFrame)
|
||||
pendingDeleteResources.insert(res);
|
||||
else
|
||||
delete res;
|
||||
}
|
||||
|
||||
void addCleanupCallback(const QRhi::CleanupCallback &callback)
|
||||
{
|
||||
cleanupCallbacks.append(callback);
|
||||
}
|
||||
|
||||
bool sanityCheckGraphicsPipeline(QRhiGraphicsPipeline *ps);
|
||||
bool sanityCheckShaderResourceBindings(QRhiShaderResourceBindings *srb);
|
||||
void updateLayoutDesc(QRhiShaderResourceBindings *srb);
|
||||
|
||||
quint32 pipelineCacheRhiId() const
|
||||
{
|
||||
const quint32 ver = (QT_VERSION_MAJOR << 16) | (QT_VERSION_MINOR << 8) | (QT_VERSION_PATCH);
|
||||
return (quint32(implType) << 24) | ver;
|
||||
}
|
||||
|
||||
void pipelineCreationStart()
|
||||
{
|
||||
pipelineCreationTimer.start();
|
||||
}
|
||||
|
||||
void pipelineCreationEnd()
|
||||
{
|
||||
accumulatedPipelineCreationTime += pipelineCreationTimer.elapsed();
|
||||
}
|
||||
|
||||
qint64 totalPipelineCreationTime() const
|
||||
{
|
||||
return accumulatedPipelineCreationTime;
|
||||
}
|
||||
|
||||
QRhiVertexInputAttribute::Format shaderDescVariableFormatToVertexInputFormat(QShaderDescription::VariableType type) const;
|
||||
quint32 byteSizePerVertexForVertexInputFormat(QRhiVertexInputAttribute::Format format) const;
|
||||
|
||||
static const QRhiShaderResourceBinding::Data *shaderResourceBindingData(const QRhiShaderResourceBinding &binding)
|
||||
{
|
||||
return &binding.d;
|
||||
}
|
||||
|
||||
static QRhiShaderResourceBinding::Data *shaderResourceBindingData(QRhiShaderResourceBinding &binding)
|
||||
{
|
||||
return &binding.d;
|
||||
}
|
||||
|
||||
static bool sortedBindingLessThan(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b)
|
||||
{
|
||||
return a.d.binding < b.d.binding;
|
||||
}
|
||||
|
||||
QRhi *q;
|
||||
|
||||
static const int MAX_SHADER_CACHE_ENTRIES = 128;
|
||||
|
||||
bool debugMarkers = false;
|
||||
int currentFrameSlot = 0; // for vk, mtl, and similar. unused by gl and d3d11.
|
||||
bool inFrame = false;
|
||||
|
||||
private:
|
||||
QRhi::Implementation implType;
|
||||
QThread *implThread;
|
||||
QVarLengthArray<QRhiResourceUpdateBatch *, 4> resUpdPool;
|
||||
quint64 resUpdPoolMap = 0;
|
||||
int lastResUpdIdx = -1;
|
||||
QHash<QRhiResource *, bool> resources;
|
||||
QSet<QRhiResource *> pendingDeleteResources;
|
||||
QVarLengthArray<QRhi::CleanupCallback, 4> cleanupCallbacks;
|
||||
QElapsedTimer pipelineCreationTimer;
|
||||
qint64 accumulatedPipelineCreationTime = 0;
|
||||
|
||||
friend class QRhi;
|
||||
friend class QRhiResourceUpdateBatchPrivate;
|
||||
};
|
||||
|
||||
enum QRhiTargetRectBoundMode
|
||||
{
|
||||
UnBounded,
|
||||
Bounded
|
||||
};
|
||||
|
||||
template<QRhiTargetRectBoundMode boundingMode, typename T, size_t N>
|
||||
bool qrhi_toTopLeftRenderTargetRect(const QSize &outputSize, const std::array<T, N> &r,
|
||||
T *x, T *y, T *w, T *h)
|
||||
{
|
||||
// x,y are bottom-left in QRhiScissor and QRhiViewport but top-left in
|
||||
// Vulkan/Metal/D3D. Our input is an OpenGL-style scissor rect where both
|
||||
// negative x or y, and partly or completely out of bounds rects are
|
||||
// allowed. The only thing the input here cannot have is a negative width
|
||||
// or height. We must handle all other input gracefully, clamping to a zero
|
||||
// width or height rect in the worst case, and ensuring the resulting rect
|
||||
// is inside the rendertarget's bounds because some APIs' validation/debug
|
||||
// layers are allergic to out of bounds scissor rects.
|
||||
|
||||
const T outputWidth = outputSize.width();
|
||||
const T outputHeight = outputSize.height();
|
||||
const T inputWidth = r[2];
|
||||
const T inputHeight = r[3];
|
||||
|
||||
if (inputWidth < 0 || inputHeight < 0)
|
||||
return false;
|
||||
|
||||
*x = r[0];
|
||||
*y = outputHeight - (r[1] + inputHeight);
|
||||
*w = inputWidth;
|
||||
*h = inputHeight;
|
||||
|
||||
if (boundingMode == Bounded) {
|
||||
const T widthOffset = *x < 0 ? -*x : 0;
|
||||
const T heightOffset = *y < 0 ? -*y : 0;
|
||||
*w = *x < outputWidth ? qMax<T>(0, inputWidth - widthOffset) : 0;
|
||||
*h = *y < outputHeight ? qMax<T>(0, inputHeight - heightOffset) : 0;
|
||||
|
||||
if (outputWidth > 0)
|
||||
*x = qBound<T>(0, *x, outputWidth - 1);
|
||||
if (outputHeight > 0)
|
||||
*y = qBound<T>(0, *y, outputHeight - 1);
|
||||
|
||||
if (*x + *w > outputWidth)
|
||||
*w = qMax<T>(0, outputWidth - *x);
|
||||
if (*y + *h > outputHeight)
|
||||
*h = qMax<T>(0, outputHeight - *y);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct QRhiBufferDataPrivate
|
||||
{
|
||||
Q_DISABLE_COPY_MOVE(QRhiBufferDataPrivate)
|
||||
QRhiBufferDataPrivate() { }
|
||||
~QRhiBufferDataPrivate() { delete[] largeData; }
|
||||
int ref = 1;
|
||||
quint32 size = 0;
|
||||
quint32 largeAlloc = 0;
|
||||
char *largeData = nullptr;
|
||||
static constexpr quint32 SMALL_DATA_SIZE = 1024;
|
||||
char data[SMALL_DATA_SIZE];
|
||||
};
|
||||
|
||||
// no detach-with-contents, no atomic refcount, no shrink
|
||||
class QRhiBufferData
|
||||
{
|
||||
public:
|
||||
QRhiBufferData() = default;
|
||||
~QRhiBufferData()
|
||||
{
|
||||
if (d && !--d->ref)
|
||||
delete d;
|
||||
}
|
||||
QRhiBufferData(const QRhiBufferData &other)
|
||||
: d(other.d)
|
||||
{
|
||||
if (d)
|
||||
d->ref += 1;
|
||||
}
|
||||
QRhiBufferData &operator=(const QRhiBufferData &other)
|
||||
{
|
||||
if (d == other.d)
|
||||
return *this;
|
||||
if (other.d)
|
||||
other.d->ref += 1;
|
||||
if (d && !--d->ref)
|
||||
delete d;
|
||||
d = other.d;
|
||||
return *this;
|
||||
}
|
||||
const char *constData() const
|
||||
{
|
||||
return d->size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE ? d->data : d->largeData;
|
||||
}
|
||||
quint32 size() const
|
||||
{
|
||||
return d->size;
|
||||
}
|
||||
void assign(const char *s, quint32 size)
|
||||
{
|
||||
if (!d) {
|
||||
d = new QRhiBufferDataPrivate;
|
||||
} else if (d->ref != 1) {
|
||||
d->ref -= 1;
|
||||
d = new QRhiBufferDataPrivate;
|
||||
}
|
||||
d->size = size;
|
||||
if (size <= QRhiBufferDataPrivate::SMALL_DATA_SIZE) {
|
||||
memcpy(d->data, s, size);
|
||||
} else {
|
||||
if (d->largeAlloc < size) {
|
||||
delete[] d->largeData;
|
||||
d->largeAlloc = size;
|
||||
d->largeData = new char[size];
|
||||
}
|
||||
memcpy(d->largeData, s, size);
|
||||
}
|
||||
}
|
||||
private:
|
||||
QRhiBufferDataPrivate *d = nullptr;
|
||||
};
|
||||
|
||||
Q_DECLARE_TYPEINFO(QRhiBufferData, Q_RELOCATABLE_TYPE);
|
||||
|
||||
class QRhiResourceUpdateBatchPrivate
|
||||
{
|
||||
public:
|
||||
struct BufferOp {
|
||||
enum Type {
|
||||
DynamicUpdate,
|
||||
StaticUpload,
|
||||
Read
|
||||
};
|
||||
Type type;
|
||||
QRhiBuffer *buf;
|
||||
quint32 offset;
|
||||
QRhiBufferData data;
|
||||
quint32 readSize;
|
||||
QRhiReadbackResult *result;
|
||||
|
||||
static BufferOp dynamicUpdate(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
|
||||
{
|
||||
BufferOp op = {};
|
||||
op.type = DynamicUpdate;
|
||||
op.buf = buf;
|
||||
op.offset = offset;
|
||||
const int effectiveSize = size ? size : buf->size();
|
||||
op.data.assign(reinterpret_cast<const char *>(data), effectiveSize);
|
||||
return op;
|
||||
}
|
||||
|
||||
static void changeToDynamicUpdate(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
|
||||
{
|
||||
op->type = DynamicUpdate;
|
||||
op->buf = buf;
|
||||
op->offset = offset;
|
||||
const int effectiveSize = size ? size : buf->size();
|
||||
op->data.assign(reinterpret_cast<const char *>(data), effectiveSize);
|
||||
}
|
||||
|
||||
static BufferOp staticUpload(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
|
||||
{
|
||||
BufferOp op = {};
|
||||
op.type = StaticUpload;
|
||||
op.buf = buf;
|
||||
op.offset = offset;
|
||||
const int effectiveSize = size ? size : buf->size();
|
||||
op.data.assign(reinterpret_cast<const char *>(data), effectiveSize);
|
||||
return op;
|
||||
}
|
||||
|
||||
static void changeToStaticUpload(BufferOp *op, QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
|
||||
{
|
||||
op->type = StaticUpload;
|
||||
op->buf = buf;
|
||||
op->offset = offset;
|
||||
const int effectiveSize = size ? size : buf->size();
|
||||
op->data.assign(reinterpret_cast<const char *>(data), effectiveSize);
|
||||
}
|
||||
|
||||
static BufferOp read(QRhiBuffer *buf, quint32 offset, quint32 size, QRhiReadbackResult *result)
|
||||
{
|
||||
BufferOp op = {};
|
||||
op.type = Read;
|
||||
op.buf = buf;
|
||||
op.offset = offset;
|
||||
op.readSize = size;
|
||||
op.result = result;
|
||||
return op;
|
||||
}
|
||||
};
|
||||
|
||||
struct TextureOp {
|
||||
enum Type {
|
||||
Upload,
|
||||
Copy,
|
||||
Read,
|
||||
GenMips
|
||||
};
|
||||
Type type;
|
||||
QRhiTexture *dst;
|
||||
// Specifying multiple uploads for a subresource must be supported.
|
||||
// In the backend this can then end up, where applicable, as a
|
||||
// single, batched copy operation with only one set of barriers.
|
||||
// This helps when doing for example glyph cache fills.
|
||||
using MipLevelUploadList = std::array<QVector<QRhiTextureSubresourceUploadDescription>, QRhi::MAX_MIP_LEVELS>;
|
||||
QVarLengthArray<MipLevelUploadList, 6> subresDesc;
|
||||
QRhiTexture *src;
|
||||
QRhiTextureCopyDescription desc;
|
||||
QRhiReadbackDescription rb;
|
||||
QRhiReadbackResult *result;
|
||||
|
||||
static TextureOp upload(QRhiTexture *tex, const QRhiTextureUploadDescription &desc)
|
||||
{
|
||||
TextureOp op = {};
|
||||
op.type = Upload;
|
||||
op.dst = tex;
|
||||
int maxLayer = -1;
|
||||
for (auto it = desc.cbeginEntries(), itEnd = desc.cendEntries(); it != itEnd; ++it) {
|
||||
if (it->layer() > maxLayer)
|
||||
maxLayer = it->layer();
|
||||
}
|
||||
op.subresDesc.resize(maxLayer + 1);
|
||||
for (auto it = desc.cbeginEntries(), itEnd = desc.cendEntries(); it != itEnd; ++it)
|
||||
op.subresDesc[it->layer()][it->level()].append(it->description());
|
||||
return op;
|
||||
}
|
||||
|
||||
static TextureOp copy(QRhiTexture *dst, QRhiTexture *src, const QRhiTextureCopyDescription &desc)
|
||||
{
|
||||
TextureOp op = {};
|
||||
op.type = Copy;
|
||||
op.dst = dst;
|
||||
op.src = src;
|
||||
op.desc = desc;
|
||||
return op;
|
||||
}
|
||||
|
||||
static TextureOp read(const QRhiReadbackDescription &rb, QRhiReadbackResult *result)
|
||||
{
|
||||
TextureOp op = {};
|
||||
op.type = Read;
|
||||
op.rb = rb;
|
||||
op.result = result;
|
||||
return op;
|
||||
}
|
||||
|
||||
static TextureOp genMips(QRhiTexture *tex)
|
||||
{
|
||||
TextureOp op = {};
|
||||
op.type = GenMips;
|
||||
op.dst = tex;
|
||||
return op;
|
||||
}
|
||||
};
|
||||
|
||||
int activeBufferOpCount = 0; // this is the real number of used elements in bufferOps, not bufferOps.count()
|
||||
static const int BUFFER_OPS_STATIC_ALLOC = 1024;
|
||||
QVarLengthArray<BufferOp, BUFFER_OPS_STATIC_ALLOC> bufferOps;
|
||||
|
||||
int activeTextureOpCount = 0; // this is the real number of used elements in textureOps, not textureOps.count()
|
||||
static const int TEXTURE_OPS_STATIC_ALLOC = 256;
|
||||
QVarLengthArray<TextureOp, TEXTURE_OPS_STATIC_ALLOC> textureOps;
|
||||
|
||||
QRhiResourceUpdateBatch *q = nullptr;
|
||||
QRhiImplementation *rhi = nullptr;
|
||||
int poolIndex = -1;
|
||||
|
||||
void free();
|
||||
void merge(QRhiResourceUpdateBatchPrivate *other);
|
||||
bool hasOptimalCapacity() const;
|
||||
void trimOpLists();
|
||||
|
||||
static QRhiResourceUpdateBatchPrivate *get(QRhiResourceUpdateBatch *b) { return b->d; }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct QRhiBatchedBindings
|
||||
{
|
||||
void feed(int binding, T resource) { // binding must be strictly increasing
|
||||
if (curBinding == -1 || binding > curBinding + 1) {
|
||||
finish();
|
||||
curBatch.startBinding = binding;
|
||||
curBatch.resources.clear();
|
||||
curBatch.resources.append(resource);
|
||||
} else {
|
||||
Q_ASSERT(binding == curBinding + 1);
|
||||
curBatch.resources.append(resource);
|
||||
}
|
||||
curBinding = binding;
|
||||
}
|
||||
|
||||
bool finish() {
|
||||
if (!curBatch.resources.isEmpty())
|
||||
batches.append(curBatch);
|
||||
return !batches.isEmpty();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
batches.clear();
|
||||
curBatch.resources.clear();
|
||||
curBinding = -1;
|
||||
}
|
||||
|
||||
struct Batch {
|
||||
uint startBinding;
|
||||
QVarLengthArray<T, 4> resources;
|
||||
|
||||
bool operator==(const Batch &other) const
|
||||
{
|
||||
return startBinding == other.startBinding && resources == other.resources;
|
||||
}
|
||||
|
||||
bool operator!=(const Batch &other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
};
|
||||
|
||||
QVarLengthArray<Batch, 4> batches; // sorted by startBinding
|
||||
|
||||
bool operator==(const QRhiBatchedBindings<T> &other) const
|
||||
{
|
||||
return batches == other.batches;
|
||||
}
|
||||
|
||||
bool operator!=(const QRhiBatchedBindings<T> &other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
private:
|
||||
Batch curBatch;
|
||||
int curBinding = -1;
|
||||
};
|
||||
|
||||
class QRhiGlobalObjectIdGenerator
|
||||
{
|
||||
public:
|
||||
#ifdef Q_ATOMIC_INT64_IS_SUPPORTED
|
||||
using Type = quint64;
|
||||
#else
|
||||
using Type = quint32;
|
||||
#endif
|
||||
static Type newId();
|
||||
};
|
||||
|
||||
class QRhiPassResourceTracker
|
||||
{
|
||||
public:
|
||||
bool isEmpty() const;
|
||||
void reset();
|
||||
|
||||
struct UsageState {
|
||||
int layout;
|
||||
int access;
|
||||
int stage;
|
||||
};
|
||||
|
||||
enum BufferStage {
|
||||
BufVertexInputStage,
|
||||
BufVertexStage,
|
||||
BufTCStage,
|
||||
BufTEStage,
|
||||
BufFragmentStage,
|
||||
BufComputeStage,
|
||||
BufGeometryStage
|
||||
};
|
||||
|
||||
enum BufferAccess {
|
||||
BufVertexInput,
|
||||
BufIndexRead,
|
||||
BufUniformRead,
|
||||
BufStorageLoad,
|
||||
BufStorageStore,
|
||||
BufStorageLoadStore
|
||||
};
|
||||
|
||||
void registerBuffer(QRhiBuffer *buf, int slot, BufferAccess *access, BufferStage *stage,
|
||||
const UsageState &state);
|
||||
|
||||
enum TextureStage {
|
||||
TexVertexStage,
|
||||
TexTCStage,
|
||||
TexTEStage,
|
||||
TexFragmentStage,
|
||||
TexColorOutputStage,
|
||||
TexDepthOutputStage,
|
||||
TexComputeStage,
|
||||
TexGeometryStage
|
||||
};
|
||||
|
||||
enum TextureAccess {
|
||||
TexSample,
|
||||
TexColorOutput,
|
||||
TexDepthOutput,
|
||||
TexStorageLoad,
|
||||
TexStorageStore,
|
||||
TexStorageLoadStore
|
||||
};
|
||||
|
||||
void registerTexture(QRhiTexture *tex, TextureAccess *access, TextureStage *stage,
|
||||
const UsageState &state);
|
||||
|
||||
struct Buffer {
|
||||
int slot;
|
||||
BufferAccess access;
|
||||
BufferStage stage;
|
||||
UsageState stateAtPassBegin;
|
||||
};
|
||||
|
||||
using BufferIterator = QHash<QRhiBuffer *, Buffer>::const_iterator;
|
||||
BufferIterator cbeginBuffers() const { return m_buffers.cbegin(); }
|
||||
BufferIterator cendBuffers() const { return m_buffers.cend(); }
|
||||
|
||||
struct Texture {
|
||||
TextureAccess access;
|
||||
TextureStage stage;
|
||||
UsageState stateAtPassBegin;
|
||||
};
|
||||
|
||||
using TextureIterator = QHash<QRhiTexture *, Texture>::const_iterator;
|
||||
TextureIterator cbeginTextures() const { return m_textures.cbegin(); }
|
||||
TextureIterator cendTextures() const { return m_textures.cend(); }
|
||||
|
||||
static BufferStage toPassTrackerBufferStage(QRhiShaderResourceBinding::StageFlags stages);
|
||||
static TextureStage toPassTrackerTextureStage(QRhiShaderResourceBinding::StageFlags stages);
|
||||
|
||||
private:
|
||||
QHash<QRhiBuffer *, Buffer> m_buffers;
|
||||
QHash<QRhiTexture *, Texture> m_textures;
|
||||
};
|
||||
|
||||
Q_DECLARE_TYPEINFO(QRhiPassResourceTracker::Buffer, Q_RELOCATABLE_TYPE);
|
||||
Q_DECLARE_TYPEINFO(QRhiPassResourceTracker::Texture, Q_RELOCATABLE_TYPE);
|
||||
|
||||
template<typename T, int GROW = 1024>
|
||||
class QRhiBackendCommandList
|
||||
{
|
||||
public:
|
||||
QRhiBackendCommandList() = default;
|
||||
~QRhiBackendCommandList() { delete[] v; }
|
||||
inline void reset() { p = 0; }
|
||||
inline bool isEmpty() const { return p == 0; }
|
||||
inline T &get() {
|
||||
if (p == a) {
|
||||
a += GROW;
|
||||
T *nv = new T[a];
|
||||
if (v) {
|
||||
memcpy(nv, v, p * sizeof(T));
|
||||
delete[] v;
|
||||
}
|
||||
v = nv;
|
||||
}
|
||||
return v[p++];
|
||||
}
|
||||
inline void unget() { --p; }
|
||||
inline T *cbegin() const { return v; }
|
||||
inline T *cend() const { return v + p; }
|
||||
inline T *begin() { return v; }
|
||||
inline T *end() { return v + p; }
|
||||
private:
|
||||
Q_DISABLE_COPY(QRhiBackendCommandList)
|
||||
T *v = nullptr;
|
||||
int a = 0;
|
||||
int p = 0;
|
||||
};
|
||||
|
||||
struct QRhiRenderTargetAttachmentTracker
|
||||
{
|
||||
struct ResId { quint64 id; uint generation; };
|
||||
using ResIdList = QVarLengthArray<ResId, 8 * 2 + 1>; // color, resolve, ds
|
||||
|
||||
template<typename TexType, typename RenderBufferType>
|
||||
static void updateResIdList(const QRhiTextureRenderTargetDescription &desc, ResIdList *dst);
|
||||
|
||||
template<typename TexType, typename RenderBufferType>
|
||||
static bool isUpToDate(const QRhiTextureRenderTargetDescription &desc, const ResIdList ¤tResIdList);
|
||||
};
|
||||
|
||||
inline bool operator==(const QRhiRenderTargetAttachmentTracker::ResId &a, const QRhiRenderTargetAttachmentTracker::ResId &b)
|
||||
{
|
||||
return a.id == b.id && a.generation == b.generation;
|
||||
}
|
||||
|
||||
inline bool operator!=(const QRhiRenderTargetAttachmentTracker::ResId &a, const QRhiRenderTargetAttachmentTracker::ResId &b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
template<typename TexType, typename RenderBufferType>
|
||||
void QRhiRenderTargetAttachmentTracker::updateResIdList(const QRhiTextureRenderTargetDescription &desc, ResIdList *dst)
|
||||
{
|
||||
const bool hasDepthStencil = desc.depthStencilBuffer() || desc.depthTexture();
|
||||
dst->resize(desc.colorAttachmentCount() * 2 + (hasDepthStencil ? 1 : 0));
|
||||
int n = 0;
|
||||
for (auto it = desc.cbeginColorAttachments(), itEnd = desc.cendColorAttachments(); it != itEnd; ++it, ++n) {
|
||||
const QRhiColorAttachment &colorAtt(*it);
|
||||
if (colorAtt.texture()) {
|
||||
TexType *texD = QRHI_RES(TexType, colorAtt.texture());
|
||||
(*dst)[n] = { texD->globalResourceId(), texD->generation };
|
||||
} else if (colorAtt.renderBuffer()) {
|
||||
RenderBufferType *rbD = QRHI_RES(RenderBufferType, colorAtt.renderBuffer());
|
||||
(*dst)[n] = { rbD->globalResourceId(), rbD->generation };
|
||||
} else {
|
||||
(*dst)[n] = { 0, 0 };
|
||||
}
|
||||
++n;
|
||||
if (colorAtt.resolveTexture()) {
|
||||
TexType *texD = QRHI_RES(TexType, colorAtt.resolveTexture());
|
||||
(*dst)[n] = { texD->globalResourceId(), texD->generation };
|
||||
} else {
|
||||
(*dst)[n] = { 0, 0 };
|
||||
}
|
||||
}
|
||||
if (hasDepthStencil) {
|
||||
if (desc.depthTexture()) {
|
||||
TexType *depthTexD = QRHI_RES(TexType, desc.depthTexture());
|
||||
(*dst)[n] = { depthTexD->globalResourceId(), depthTexD->generation };
|
||||
} else if (desc.depthStencilBuffer()) {
|
||||
RenderBufferType *depthRbD = QRHI_RES(RenderBufferType, desc.depthStencilBuffer());
|
||||
(*dst)[n] = { depthRbD->globalResourceId(), depthRbD->generation };
|
||||
} else {
|
||||
(*dst)[n] = { 0, 0 };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TexType, typename RenderBufferType>
|
||||
bool QRhiRenderTargetAttachmentTracker::isUpToDate(const QRhiTextureRenderTargetDescription &desc, const ResIdList ¤tResIdList)
|
||||
{
|
||||
// Just as setShaderResources() recognizes if an srb's referenced
|
||||
// resources have been rebuilt (got a create() since the srb's
|
||||
// create()), we should do the same for the textures and renderbuffers
|
||||
// referenced from the rendertarget. It is not uncommon that a texture
|
||||
// or ds buffer gets resized due to following a window size in some
|
||||
// form, which involves a create() on them. It is then nice if the
|
||||
// render target auto-rebuilds in beginPass().
|
||||
|
||||
ResIdList resIdList;
|
||||
updateResIdList<TexType, RenderBufferType>(desc, &resIdList);
|
||||
return resIdList == currentResIdList;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T *qrhi_objectFromProxyData(QRhiSwapChainProxyData *pd, QWindow *window, QRhi::Implementation impl, uint objectIndex)
|
||||
{
|
||||
Q_ASSERT(objectIndex < std::size(pd->reserved));
|
||||
if (!pd->reserved[objectIndex]) // // was not set, no other choice, do it here, whatever thread this is
|
||||
*pd = QRhi::updateSwapChainProxyData(impl, window);
|
||||
return static_cast<T *>(pd->reserved[objectIndex]);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
172
src/gui/rhi/qrhi_platform.h
Normal file
172
src/gui/rhi/qrhi_platform.h
Normal file
@ -0,0 +1,172 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QRHIPLATFORM_H
|
||||
#define QRHIPLATFORM_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is part of the RHI API, with limited compatibility guarantees.
|
||||
// Usage of this API may make your code source and binary incompatible with
|
||||
// future versions of Qt.
|
||||
//
|
||||
|
||||
#include <rhi/qrhi.h>
|
||||
|
||||
#if QT_CONFIG(opengl)
|
||||
#include <QtGui/qsurfaceformat.h>
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(vulkan)
|
||||
#include <QtGui/qvulkaninstance.h>
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS) || defined(Q_QDOC)
|
||||
Q_FORWARD_DECLARE_OBJC_CLASS(MTLDevice);
|
||||
Q_FORWARD_DECLARE_OBJC_CLASS(MTLCommandQueue);
|
||||
Q_FORWARD_DECLARE_OBJC_CLASS(MTLCommandBuffer);
|
||||
Q_FORWARD_DECLARE_OBJC_CLASS(MTLRenderCommandEncoder);
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
struct Q_GUI_EXPORT QRhiNullInitParams : public QRhiInitParams
|
||||
{
|
||||
};
|
||||
|
||||
struct Q_GUI_EXPORT QRhiNullNativeHandles : public QRhiNativeHandles
|
||||
{
|
||||
};
|
||||
|
||||
#if QT_CONFIG(opengl) || defined(Q_QDOC)
|
||||
|
||||
class QOpenGLContext;
|
||||
class QOffscreenSurface;
|
||||
class QSurface;
|
||||
class QWindow;
|
||||
|
||||
struct Q_GUI_EXPORT QRhiGles2InitParams : public QRhiInitParams
|
||||
{
|
||||
QRhiGles2InitParams();
|
||||
|
||||
QSurfaceFormat format;
|
||||
QSurface *fallbackSurface = nullptr;
|
||||
QWindow *window = nullptr;
|
||||
QOpenGLContext *shareContext = nullptr;
|
||||
|
||||
static QOffscreenSurface *newFallbackSurface(const QSurfaceFormat &format = QSurfaceFormat::defaultFormat());
|
||||
};
|
||||
|
||||
struct Q_GUI_EXPORT QRhiGles2NativeHandles : public QRhiNativeHandles
|
||||
{
|
||||
QOpenGLContext *context = nullptr;
|
||||
};
|
||||
|
||||
#endif // opengl/qdoc
|
||||
|
||||
#if QT_CONFIG(vulkan) || defined(Q_QDOC)
|
||||
|
||||
struct Q_GUI_EXPORT QRhiVulkanInitParams : public QRhiInitParams
|
||||
{
|
||||
QVulkanInstance *inst = nullptr;
|
||||
QWindow *window = nullptr;
|
||||
QByteArrayList deviceExtensions;
|
||||
|
||||
static QByteArrayList preferredInstanceExtensions();
|
||||
static QByteArrayList preferredExtensionsForImportedDevice();
|
||||
};
|
||||
|
||||
struct Q_GUI_EXPORT QRhiVulkanNativeHandles : public QRhiNativeHandles
|
||||
{
|
||||
// to import a physical device (always required)
|
||||
VkPhysicalDevice physDev = VK_NULL_HANDLE;
|
||||
// to import a device and queue
|
||||
VkDevice dev = VK_NULL_HANDLE;
|
||||
quint32 gfxQueueFamilyIdx = 0;
|
||||
quint32 gfxQueueIdx = 0;
|
||||
VkQueue gfxQueue = VK_NULL_HANDLE;
|
||||
// and optionally, the mem allocator
|
||||
void *vmemAllocator = nullptr;
|
||||
};
|
||||
|
||||
struct Q_GUI_EXPORT QRhiVulkanCommandBufferNativeHandles : public QRhiNativeHandles
|
||||
{
|
||||
VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
struct Q_GUI_EXPORT QRhiVulkanRenderPassNativeHandles : public QRhiNativeHandles
|
||||
{
|
||||
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||
};
|
||||
|
||||
#endif // vulkan/qdoc
|
||||
|
||||
#if defined(Q_OS_WIN) || defined(Q_QDOC)
|
||||
|
||||
// no d3d includes here, to prevent precompiled header mess due to COM, hence the void pointers
|
||||
|
||||
struct Q_GUI_EXPORT QRhiD3D11InitParams : public QRhiInitParams
|
||||
{
|
||||
bool enableDebugLayer = false;
|
||||
};
|
||||
|
||||
struct Q_GUI_EXPORT QRhiD3D11NativeHandles : public QRhiNativeHandles
|
||||
{
|
||||
// to import a device and a context
|
||||
void *dev = nullptr;
|
||||
void *context = nullptr;
|
||||
// alternatively, to specify the device feature level and/or the adapter to use
|
||||
int featureLevel = 0;
|
||||
quint32 adapterLuidLow = 0;
|
||||
qint32 adapterLuidHigh = 0;
|
||||
};
|
||||
|
||||
struct Q_GUI_EXPORT QRhiD3D12InitParams : public QRhiInitParams
|
||||
{
|
||||
bool enableDebugLayer = false;
|
||||
};
|
||||
|
||||
struct Q_GUI_EXPORT QRhiD3D12NativeHandles : public QRhiNativeHandles
|
||||
{
|
||||
// to import a device
|
||||
void *dev = nullptr;
|
||||
int minimumFeatureLevel = 0;
|
||||
// to just specify the adapter to use, set these and leave dev set to null
|
||||
quint32 adapterLuidLow = 0;
|
||||
qint32 adapterLuidHigh = 0;
|
||||
// in addition, can specify the command queue to use
|
||||
void *commandQueue = nullptr;
|
||||
};
|
||||
|
||||
struct Q_GUI_EXPORT QRhiD3D12CommandBufferNativeHandles : public QRhiNativeHandles
|
||||
{
|
||||
void *commandList = nullptr; // ID3D12GraphicsCommandList
|
||||
};
|
||||
|
||||
#endif // WIN/QDOC
|
||||
|
||||
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS) || defined(Q_QDOC)
|
||||
|
||||
struct Q_GUI_EXPORT QRhiMetalInitParams : public QRhiInitParams
|
||||
{
|
||||
};
|
||||
|
||||
struct Q_GUI_EXPORT QRhiMetalNativeHandles : public QRhiNativeHandles
|
||||
{
|
||||
MTLDevice *dev = nullptr;
|
||||
MTLCommandQueue *cmdQueue = nullptr;
|
||||
};
|
||||
|
||||
struct Q_GUI_EXPORT QRhiMetalCommandBufferNativeHandles : public QRhiNativeHandles
|
||||
{
|
||||
MTLCommandBuffer *commandBuffer = nullptr;
|
||||
MTLRenderCommandEncoder *encoder = nullptr;
|
||||
};
|
||||
|
||||
#endif // MACOS/IOS/QDOC
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
@ -1,8 +1,8 @@
|
||||
// Copyright (C) 2019 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include "qrhid3d11_p_p.h"
|
||||
#include "qshader_p.h"
|
||||
#include "qrhid3d11_p.h"
|
||||
#include "qshader.h"
|
||||
#include "vs_test_p.h"
|
||||
#include <QWindow>
|
||||
#include <qmath.h>
|
||||
@ -28,10 +28,13 @@ using namespace Qt::StringLiterals;
|
||||
|
||||
/*!
|
||||
\class QRhiD3D11InitParams
|
||||
\internal
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
\brief Direct3D 11 specific initialization parameters.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QRhi
|
||||
for details.
|
||||
|
||||
A D3D11-based QRhi needs no special parameters for initialization. If
|
||||
desired, enableDebugLayer can be set to \c true to enable the Direct3D
|
||||
debug layer. This can be useful during development, but should be avoided
|
||||
@ -69,17 +72,47 @@ using namespace Qt::StringLiterals;
|
||||
Initialization will fail otherwise.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiD3D11InitParams::enableDebugLayer
|
||||
|
||||
When set to true, a debug device is created, assuming the debug layer is
|
||||
available. The default value is false.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QRhiD3D11NativeHandles
|
||||
\internal
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
\brief Holds the D3D device and device context used by the QRhi.
|
||||
|
||||
\note The class uses \c{void *} as the type since including the COM-based
|
||||
\c{d3d11.h} headers is not acceptable here. The actual types are
|
||||
\c{ID3D11Device *} and \c{ID3D11DeviceContext *}.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QRhi
|
||||
for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiD3D11NativeHandles::dev
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiD3D11NativeHandles::context
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiD3D11NativeHandles::featureLevel
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiD3D11NativeHandles::adapterLuidLow
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiD3D11NativeHandles::adapterLuidHigh
|
||||
*/
|
||||
|
||||
// help mingw with its ancient sdk headers
|
||||
#ifndef DXGI_ADAPTER_FLAG_SOFTWARE
|
||||
#define DXGI_ADAPTER_FLAG_SOFTWARE 2
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Copyright (C) 2019 The Qt Company Ltd.
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QRHID3D11_H
|
||||
#define QRHID3D11_H
|
||||
#ifndef QRHID3D11_P_H
|
||||
#define QRHID3D11_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
@ -15,28 +15,838 @@
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <private/qrhi_p.h>
|
||||
#include "qrhi_p.h"
|
||||
#include "qshaderdescription.h"
|
||||
#include <QWindow>
|
||||
|
||||
// no d3d includes here, to prevent precompiled header mess due to COM
|
||||
#include <d3d11_1.h>
|
||||
#include <dxgi1_6.h>
|
||||
#include <dcomp.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
struct Q_GUI_EXPORT QRhiD3D11InitParams : public QRhiInitParams
|
||||
class QRhiD3D11;
|
||||
|
||||
struct QD3D11Buffer : public QRhiBuffer
|
||||
{
|
||||
bool enableDebugLayer = false;
|
||||
QD3D11Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size);
|
||||
~QD3D11Buffer();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
QRhiBuffer::NativeBuffer nativeBuffer() override;
|
||||
char *beginFullDynamicBufferUpdateForCurrentFrame() override;
|
||||
void endFullDynamicBufferUpdateForCurrentFrame() override;
|
||||
|
||||
ID3D11UnorderedAccessView *unorderedAccessView(quint32 offset);
|
||||
|
||||
ID3D11Buffer *buffer = nullptr;
|
||||
char *dynBuf = nullptr;
|
||||
bool hasPendingDynamicUpdates = false;
|
||||
QHash<quint32, ID3D11UnorderedAccessView *> uavs;
|
||||
uint generation = 0;
|
||||
friend class QRhiD3D11;
|
||||
};
|
||||
|
||||
struct Q_GUI_EXPORT QRhiD3D11NativeHandles : public QRhiNativeHandles
|
||||
struct QD3D11RenderBuffer : public QRhiRenderBuffer
|
||||
{
|
||||
// to import a device and a context
|
||||
void *dev = nullptr;
|
||||
void *context = nullptr;
|
||||
// alternatively, to specify the device feature level and/or the adapter to use
|
||||
int featureLevel = 0;
|
||||
quint32 adapterLuidLow = 0;
|
||||
qint32 adapterLuidHigh = 0;
|
||||
QD3D11RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint);
|
||||
~QD3D11RenderBuffer();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
QRhiTexture::Format backingFormat() const override;
|
||||
|
||||
ID3D11Texture2D *tex = nullptr;
|
||||
ID3D11DepthStencilView *dsv = nullptr;
|
||||
ID3D11RenderTargetView *rtv = nullptr;
|
||||
DXGI_FORMAT dxgiFormat;
|
||||
DXGI_SAMPLE_DESC sampleDesc;
|
||||
uint generation = 0;
|
||||
friend class QRhiD3D11;
|
||||
};
|
||||
|
||||
struct QD3D11Texture : public QRhiTexture
|
||||
{
|
||||
QD3D11Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
|
||||
int arraySize, int sampleCount, Flags flags);
|
||||
~QD3D11Texture();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
bool createFrom(NativeTexture src) override;
|
||||
NativeTexture nativeTexture() override;
|
||||
|
||||
bool prepareCreate(QSize *adjustedSize = nullptr);
|
||||
bool finishCreate();
|
||||
ID3D11UnorderedAccessView *unorderedAccessViewForLevel(int level);
|
||||
ID3D11Resource *textureResource() const
|
||||
{
|
||||
if (tex)
|
||||
return tex;
|
||||
else if (tex1D)
|
||||
return tex1D;
|
||||
return tex3D;
|
||||
}
|
||||
|
||||
ID3D11Texture2D *tex = nullptr;
|
||||
ID3D11Texture3D *tex3D = nullptr;
|
||||
ID3D11Texture1D *tex1D = nullptr;
|
||||
bool owns = true;
|
||||
ID3D11ShaderResourceView *srv = nullptr;
|
||||
DXGI_FORMAT dxgiFormat;
|
||||
uint mipLevelCount = 0;
|
||||
DXGI_SAMPLE_DESC sampleDesc;
|
||||
ID3D11UnorderedAccessView *perLevelViews[QRhi::MAX_MIP_LEVELS];
|
||||
uint generation = 0;
|
||||
friend class QRhiD3D11;
|
||||
};
|
||||
|
||||
struct QD3D11Sampler : public QRhiSampler
|
||||
{
|
||||
QD3D11Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
|
||||
AddressMode u, AddressMode v, AddressMode w);
|
||||
~QD3D11Sampler();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
|
||||
ID3D11SamplerState *samplerState = nullptr;
|
||||
uint generation = 0;
|
||||
friend class QRhiD3D11;
|
||||
};
|
||||
|
||||
struct QD3D11RenderPassDescriptor : public QRhiRenderPassDescriptor
|
||||
{
|
||||
QD3D11RenderPassDescriptor(QRhiImplementation *rhi);
|
||||
~QD3D11RenderPassDescriptor();
|
||||
void destroy() override;
|
||||
bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
|
||||
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
|
||||
QVector<quint32> serializedFormat() const override;
|
||||
};
|
||||
|
||||
struct QD3D11RenderTargetData
|
||||
{
|
||||
QD3D11RenderTargetData(QRhiImplementation *)
|
||||
{
|
||||
for (int i = 0; i < MAX_COLOR_ATTACHMENTS; ++i)
|
||||
rtv[i] = nullptr;
|
||||
}
|
||||
|
||||
QD3D11RenderPassDescriptor *rp = nullptr;
|
||||
QSize pixelSize;
|
||||
float dpr = 1;
|
||||
int sampleCount = 1;
|
||||
int colorAttCount = 0;
|
||||
int dsAttCount = 0;
|
||||
|
||||
static const int MAX_COLOR_ATTACHMENTS = 8;
|
||||
ID3D11RenderTargetView *rtv[MAX_COLOR_ATTACHMENTS];
|
||||
ID3D11DepthStencilView *dsv = nullptr;
|
||||
|
||||
QRhiRenderTargetAttachmentTracker::ResIdList currentResIdList;
|
||||
};
|
||||
|
||||
struct QD3D11SwapChainRenderTarget : public QRhiSwapChainRenderTarget
|
||||
{
|
||||
QD3D11SwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain);
|
||||
~QD3D11SwapChainRenderTarget();
|
||||
void destroy() override;
|
||||
|
||||
QSize pixelSize() const override;
|
||||
float devicePixelRatio() const override;
|
||||
int sampleCount() const override;
|
||||
|
||||
QD3D11RenderTargetData d;
|
||||
};
|
||||
|
||||
struct QD3D11TextureRenderTarget : public QRhiTextureRenderTarget
|
||||
{
|
||||
QD3D11TextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
|
||||
~QD3D11TextureRenderTarget();
|
||||
void destroy() override;
|
||||
|
||||
QSize pixelSize() const override;
|
||||
float devicePixelRatio() const override;
|
||||
int sampleCount() const override;
|
||||
|
||||
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
|
||||
bool create() override;
|
||||
|
||||
QD3D11RenderTargetData d;
|
||||
bool ownsRtv[QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS];
|
||||
ID3D11RenderTargetView *rtv[QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS];
|
||||
bool ownsDsv = false;
|
||||
ID3D11DepthStencilView *dsv = nullptr;
|
||||
friend class QRhiD3D11;
|
||||
};
|
||||
|
||||
struct QD3D11ShaderResourceBindings : public QRhiShaderResourceBindings
|
||||
{
|
||||
QD3D11ShaderResourceBindings(QRhiImplementation *rhi);
|
||||
~QD3D11ShaderResourceBindings();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
void updateResources(UpdateFlags flags) override;
|
||||
|
||||
bool hasDynamicOffset = false;
|
||||
QVarLengthArray<QRhiShaderResourceBinding, 8> sortedBindings;
|
||||
uint generation = 0;
|
||||
|
||||
// Keep track of the generation number of each referenced QRhi* to be able
|
||||
// to detect that the batched bindings are out of date.
|
||||
struct BoundUniformBufferData {
|
||||
quint64 id;
|
||||
uint generation;
|
||||
};
|
||||
struct BoundSampledTextureData {
|
||||
int count;
|
||||
struct {
|
||||
quint64 texId;
|
||||
uint texGeneration;
|
||||
quint64 samplerId;
|
||||
uint samplerGeneration;
|
||||
} d[QRhiShaderResourceBinding::Data::MAX_TEX_SAMPLER_ARRAY_SIZE];
|
||||
};
|
||||
struct BoundStorageImageData {
|
||||
quint64 id;
|
||||
uint generation;
|
||||
};
|
||||
struct BoundStorageBufferData {
|
||||
quint64 id;
|
||||
uint generation;
|
||||
};
|
||||
struct BoundResourceData {
|
||||
union {
|
||||
BoundUniformBufferData ubuf;
|
||||
BoundSampledTextureData stex;
|
||||
BoundStorageImageData simage;
|
||||
BoundStorageBufferData sbuf;
|
||||
};
|
||||
};
|
||||
QVarLengthArray<BoundResourceData, 8> boundResourceData;
|
||||
|
||||
struct StageUniformBufferBatches {
|
||||
bool present = false;
|
||||
QRhiBatchedBindings<ID3D11Buffer *> ubufs;
|
||||
QRhiBatchedBindings<UINT> ubuforigbindings;
|
||||
QRhiBatchedBindings<UINT> ubufoffsets;
|
||||
QRhiBatchedBindings<UINT> ubufsizes;
|
||||
void finish() {
|
||||
present = ubufs.finish();
|
||||
ubuforigbindings.finish();
|
||||
ubufoffsets.finish();
|
||||
ubufsizes.finish();
|
||||
}
|
||||
void clear() {
|
||||
ubufs.clear();
|
||||
ubuforigbindings.clear();
|
||||
ubufoffsets.clear();
|
||||
ubufsizes.clear();
|
||||
}
|
||||
};
|
||||
|
||||
struct StageSamplerBatches {
|
||||
bool present = false;
|
||||
QRhiBatchedBindings<ID3D11SamplerState *> samplers;
|
||||
QRhiBatchedBindings<ID3D11ShaderResourceView *> shaderresources;
|
||||
void finish() {
|
||||
present = samplers.finish();
|
||||
shaderresources.finish();
|
||||
}
|
||||
void clear() {
|
||||
samplers.clear();
|
||||
shaderresources.clear();
|
||||
}
|
||||
};
|
||||
|
||||
struct StageUavBatches {
|
||||
bool present = false;
|
||||
QRhiBatchedBindings<ID3D11UnorderedAccessView *> uavs;
|
||||
void finish() {
|
||||
present = uavs.finish();
|
||||
}
|
||||
void clear() {
|
||||
uavs.clear();
|
||||
}
|
||||
};
|
||||
|
||||
StageUniformBufferBatches vsUniformBufferBatches;
|
||||
StageUniformBufferBatches hsUniformBufferBatches;
|
||||
StageUniformBufferBatches dsUniformBufferBatches;
|
||||
StageUniformBufferBatches gsUniformBufferBatches;
|
||||
StageUniformBufferBatches fsUniformBufferBatches;
|
||||
StageUniformBufferBatches csUniformBufferBatches;
|
||||
|
||||
StageSamplerBatches vsSamplerBatches;
|
||||
StageSamplerBatches hsSamplerBatches;
|
||||
StageSamplerBatches dsSamplerBatches;
|
||||
StageSamplerBatches gsSamplerBatches;
|
||||
StageSamplerBatches fsSamplerBatches;
|
||||
StageSamplerBatches csSamplerBatches;
|
||||
|
||||
StageUavBatches csUavBatches;
|
||||
|
||||
friend class QRhiD3D11;
|
||||
};
|
||||
|
||||
Q_DECLARE_TYPEINFO(QD3D11ShaderResourceBindings::BoundResourceData, Q_RELOCATABLE_TYPE);
|
||||
|
||||
struct QD3D11GraphicsPipeline : public QRhiGraphicsPipeline
|
||||
{
|
||||
QD3D11GraphicsPipeline(QRhiImplementation *rhi);
|
||||
~QD3D11GraphicsPipeline();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
|
||||
ID3D11DepthStencilState *dsState = nullptr;
|
||||
ID3D11BlendState *blendState = nullptr;
|
||||
struct {
|
||||
ID3D11VertexShader *shader = nullptr;
|
||||
QShader::NativeResourceBindingMap nativeResourceBindingMap;
|
||||
} vs;
|
||||
struct {
|
||||
ID3D11HullShader *shader = nullptr;
|
||||
QShader::NativeResourceBindingMap nativeResourceBindingMap;
|
||||
} hs;
|
||||
struct {
|
||||
ID3D11DomainShader *shader = nullptr;
|
||||
QShader::NativeResourceBindingMap nativeResourceBindingMap;
|
||||
} ds;
|
||||
struct {
|
||||
ID3D11GeometryShader *shader = nullptr;
|
||||
QShader::NativeResourceBindingMap nativeResourceBindingMap;
|
||||
} gs;
|
||||
struct {
|
||||
ID3D11PixelShader *shader = nullptr;
|
||||
QShader::NativeResourceBindingMap nativeResourceBindingMap;
|
||||
} fs;
|
||||
ID3D11InputLayout *inputLayout = nullptr;
|
||||
D3D11_PRIMITIVE_TOPOLOGY d3dTopology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||
ID3D11RasterizerState *rastState = nullptr;
|
||||
uint generation = 0;
|
||||
friend class QRhiD3D11;
|
||||
};
|
||||
|
||||
struct QD3D11ComputePipeline : public QRhiComputePipeline
|
||||
{
|
||||
QD3D11ComputePipeline(QRhiImplementation *rhi);
|
||||
~QD3D11ComputePipeline();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
|
||||
struct {
|
||||
ID3D11ComputeShader *shader = nullptr;
|
||||
QShader::NativeResourceBindingMap nativeResourceBindingMap;
|
||||
} cs;
|
||||
uint generation = 0;
|
||||
friend class QRhiD3D11;
|
||||
};
|
||||
|
||||
struct QD3D11SwapChain;
|
||||
|
||||
struct QD3D11CommandBuffer : public QRhiCommandBuffer
|
||||
{
|
||||
QD3D11CommandBuffer(QRhiImplementation *rhi);
|
||||
~QD3D11CommandBuffer();
|
||||
void destroy() override;
|
||||
|
||||
// these must be kept at a reasonably low value otherwise sizeof Command explodes
|
||||
static const int MAX_DYNAMIC_OFFSET_COUNT = 8;
|
||||
static const int MAX_VERTEX_BUFFER_BINDING_COUNT = 8;
|
||||
|
||||
struct Command {
|
||||
enum Cmd {
|
||||
ResetShaderResources,
|
||||
SetRenderTarget,
|
||||
Clear,
|
||||
Viewport,
|
||||
Scissor,
|
||||
BindVertexBuffers,
|
||||
BindIndexBuffer,
|
||||
BindGraphicsPipeline,
|
||||
BindShaderResources,
|
||||
StencilRef,
|
||||
BlendConstants,
|
||||
Draw,
|
||||
DrawIndexed,
|
||||
UpdateSubRes,
|
||||
CopySubRes,
|
||||
ResolveSubRes,
|
||||
GenMip,
|
||||
DebugMarkBegin,
|
||||
DebugMarkEnd,
|
||||
DebugMarkMsg,
|
||||
BindComputePipeline,
|
||||
Dispatch
|
||||
};
|
||||
enum ClearFlag { Color = 1, Depth = 2, Stencil = 4 };
|
||||
Cmd cmd;
|
||||
|
||||
// QRhi*/QD3D11* references should be kept at minimum (so no
|
||||
// QRhiTexture/Buffer/etc. pointers).
|
||||
union Args {
|
||||
struct {
|
||||
QRhiRenderTarget *rt;
|
||||
} setRenderTarget;
|
||||
struct {
|
||||
QRhiRenderTarget *rt;
|
||||
int mask;
|
||||
float c[4];
|
||||
float d;
|
||||
quint32 s;
|
||||
} clear;
|
||||
struct {
|
||||
float x, y, w, h;
|
||||
float d0, d1;
|
||||
} viewport;
|
||||
struct {
|
||||
int x, y, w, h;
|
||||
} scissor;
|
||||
struct {
|
||||
int startSlot;
|
||||
int slotCount;
|
||||
ID3D11Buffer *buffers[MAX_VERTEX_BUFFER_BINDING_COUNT];
|
||||
UINT offsets[MAX_VERTEX_BUFFER_BINDING_COUNT];
|
||||
UINT strides[MAX_VERTEX_BUFFER_BINDING_COUNT];
|
||||
} bindVertexBuffers;
|
||||
struct {
|
||||
ID3D11Buffer *buffer;
|
||||
quint32 offset;
|
||||
DXGI_FORMAT format;
|
||||
} bindIndexBuffer;
|
||||
struct {
|
||||
QD3D11GraphicsPipeline *ps;
|
||||
} bindGraphicsPipeline;
|
||||
struct {
|
||||
QD3D11ShaderResourceBindings *srb;
|
||||
bool offsetOnlyChange;
|
||||
int dynamicOffsetCount;
|
||||
uint dynamicOffsetPairs[MAX_DYNAMIC_OFFSET_COUNT * 2]; // binding, offsetInConstants
|
||||
} bindShaderResources;
|
||||
struct {
|
||||
QD3D11GraphicsPipeline *ps;
|
||||
quint32 ref;
|
||||
} stencilRef;
|
||||
struct {
|
||||
QD3D11GraphicsPipeline *ps;
|
||||
float c[4];
|
||||
} blendConstants;
|
||||
struct {
|
||||
QD3D11GraphicsPipeline *ps;
|
||||
quint32 vertexCount;
|
||||
quint32 instanceCount;
|
||||
quint32 firstVertex;
|
||||
quint32 firstInstance;
|
||||
} draw;
|
||||
struct {
|
||||
QD3D11GraphicsPipeline *ps;
|
||||
quint32 indexCount;
|
||||
quint32 instanceCount;
|
||||
quint32 firstIndex;
|
||||
qint32 vertexOffset;
|
||||
quint32 firstInstance;
|
||||
} drawIndexed;
|
||||
struct {
|
||||
ID3D11Resource *dst;
|
||||
UINT dstSubRes;
|
||||
bool hasDstBox;
|
||||
D3D11_BOX dstBox;
|
||||
const void *src; // must come from retain*()
|
||||
UINT srcRowPitch;
|
||||
} updateSubRes;
|
||||
struct {
|
||||
ID3D11Resource *dst;
|
||||
UINT dstSubRes;
|
||||
UINT dstX;
|
||||
UINT dstY;
|
||||
UINT dstZ;
|
||||
ID3D11Resource *src;
|
||||
UINT srcSubRes;
|
||||
bool hasSrcBox;
|
||||
D3D11_BOX srcBox;
|
||||
} copySubRes;
|
||||
struct {
|
||||
ID3D11Resource *dst;
|
||||
UINT dstSubRes;
|
||||
ID3D11Resource *src;
|
||||
UINT srcSubRes;
|
||||
DXGI_FORMAT format;
|
||||
} resolveSubRes;
|
||||
struct {
|
||||
ID3D11ShaderResourceView *srv;
|
||||
} genMip;
|
||||
struct {
|
||||
char s[64];
|
||||
} debugMark;
|
||||
struct {
|
||||
QD3D11ComputePipeline *ps;
|
||||
} bindComputePipeline;
|
||||
struct {
|
||||
UINT x;
|
||||
UINT y;
|
||||
UINT z;
|
||||
} dispatch;
|
||||
} args;
|
||||
};
|
||||
|
||||
enum PassType {
|
||||
NoPass,
|
||||
RenderPass,
|
||||
ComputePass
|
||||
};
|
||||
|
||||
QRhiBackendCommandList<Command> commands;
|
||||
PassType recordingPass;
|
||||
double lastGpuTime = 0;
|
||||
QRhiRenderTarget *currentTarget;
|
||||
QRhiGraphicsPipeline *currentGraphicsPipeline;
|
||||
QRhiComputePipeline *currentComputePipeline;
|
||||
uint currentPipelineGeneration;
|
||||
QRhiShaderResourceBindings *currentGraphicsSrb;
|
||||
QRhiShaderResourceBindings *currentComputeSrb;
|
||||
uint currentSrbGeneration;
|
||||
ID3D11Buffer *currentIndexBuffer;
|
||||
quint32 currentIndexOffset;
|
||||
DXGI_FORMAT currentIndexFormat;
|
||||
ID3D11Buffer *currentVertexBuffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
|
||||
quint32 currentVertexOffsets[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
|
||||
|
||||
QVarLengthArray<QByteArray, 4> dataRetainPool;
|
||||
QVarLengthArray<QRhiBufferData, 4> bufferDataRetainPool;
|
||||
QVarLengthArray<QImage, 4> imageRetainPool;
|
||||
|
||||
// relies heavily on implicit sharing (no copies of the actual data will be made)
|
||||
const uchar *retainData(const QByteArray &data) {
|
||||
dataRetainPool.append(data);
|
||||
return reinterpret_cast<const uchar *>(dataRetainPool.last().constData());
|
||||
}
|
||||
const uchar *retainBufferData(const QRhiBufferData &data) {
|
||||
bufferDataRetainPool.append(data);
|
||||
return reinterpret_cast<const uchar *>(bufferDataRetainPool.last().constData());
|
||||
}
|
||||
const uchar *retainImage(const QImage &image) {
|
||||
imageRetainPool.append(image);
|
||||
return imageRetainPool.last().constBits();
|
||||
}
|
||||
void resetCommands() {
|
||||
commands.reset();
|
||||
dataRetainPool.clear();
|
||||
bufferDataRetainPool.clear();
|
||||
imageRetainPool.clear();
|
||||
}
|
||||
void resetState() {
|
||||
recordingPass = NoPass;
|
||||
// do not zero lastGpuTime
|
||||
currentTarget = nullptr;
|
||||
resetCommands();
|
||||
resetCachedState();
|
||||
}
|
||||
void resetCachedState() {
|
||||
currentGraphicsPipeline = nullptr;
|
||||
currentComputePipeline = nullptr;
|
||||
currentPipelineGeneration = 0;
|
||||
currentGraphicsSrb = nullptr;
|
||||
currentComputeSrb = nullptr;
|
||||
currentSrbGeneration = 0;
|
||||
currentIndexBuffer = nullptr;
|
||||
currentIndexOffset = 0;
|
||||
currentIndexFormat = DXGI_FORMAT_R16_UINT;
|
||||
memset(currentVertexBuffers, 0, sizeof(currentVertexBuffers));
|
||||
memset(currentVertexOffsets, 0, sizeof(currentVertexOffsets));
|
||||
}
|
||||
};
|
||||
|
||||
static const int QD3D11_SWAPCHAIN_BUFFER_COUNT = 2;
|
||||
|
||||
struct QD3D11Timestamps
|
||||
{
|
||||
static const int MAX_TIMESTAMP_PAIRS = QD3D11_SWAPCHAIN_BUFFER_COUNT;
|
||||
bool active[MAX_TIMESTAMP_PAIRS] = {};
|
||||
ID3D11Query *disjointQuery[MAX_TIMESTAMP_PAIRS] = {};
|
||||
ID3D11Query *query[MAX_TIMESTAMP_PAIRS * 2] = {};
|
||||
int pairCount = 0;
|
||||
|
||||
bool prepare(int pairCount, QRhiD3D11 *rhiD);
|
||||
void destroy();
|
||||
bool tryQueryTimestamps(int idx, ID3D11DeviceContext *context, double *elapsedSec);
|
||||
};
|
||||
|
||||
struct QD3D11SwapChain : public QRhiSwapChain
|
||||
{
|
||||
QD3D11SwapChain(QRhiImplementation *rhi);
|
||||
~QD3D11SwapChain();
|
||||
void destroy() override;
|
||||
|
||||
QRhiCommandBuffer *currentFrameCommandBuffer() override;
|
||||
QRhiRenderTarget *currentFrameRenderTarget() override;
|
||||
|
||||
QSize surfacePixelSize() override;
|
||||
bool isFormatSupported(Format f) override;
|
||||
QRhiSwapChainHdrInfo hdrInfo() override;
|
||||
|
||||
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
|
||||
bool createOrResize() override;
|
||||
|
||||
void releaseBuffers();
|
||||
bool newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc,
|
||||
ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv) const;
|
||||
|
||||
QWindow *window = nullptr;
|
||||
QSize pixelSize;
|
||||
QD3D11SwapChainRenderTarget rt;
|
||||
QD3D11CommandBuffer cb;
|
||||
DXGI_FORMAT colorFormat;
|
||||
DXGI_FORMAT srgbAdjustedColorFormat;
|
||||
IDXGISwapChain *swapChain = nullptr;
|
||||
UINT swapChainFlags = 0;
|
||||
ID3D11Texture2D *backBufferTex;
|
||||
ID3D11RenderTargetView *backBufferRtv;
|
||||
static const int BUFFER_COUNT = QD3D11_SWAPCHAIN_BUFFER_COUNT;
|
||||
ID3D11Texture2D *msaaTex[BUFFER_COUNT];
|
||||
ID3D11RenderTargetView *msaaRtv[BUFFER_COUNT];
|
||||
DXGI_SAMPLE_DESC sampleDesc;
|
||||
int currentFrameSlot = 0;
|
||||
int frameCount = 0;
|
||||
QD3D11RenderBuffer *ds = nullptr;
|
||||
UINT swapInterval = 1;
|
||||
IDCompositionTarget *dcompTarget = nullptr;
|
||||
IDCompositionVisual *dcompVisual = nullptr;
|
||||
QD3D11Timestamps timestamps;
|
||||
};
|
||||
|
||||
class QRhiD3D11 : public QRhiImplementation
|
||||
{
|
||||
public:
|
||||
QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importDevice = nullptr);
|
||||
|
||||
bool create(QRhi::Flags flags) override;
|
||||
void destroy() override;
|
||||
|
||||
QRhiGraphicsPipeline *createGraphicsPipeline() override;
|
||||
QRhiComputePipeline *createComputePipeline() override;
|
||||
QRhiShaderResourceBindings *createShaderResourceBindings() override;
|
||||
QRhiBuffer *createBuffer(QRhiBuffer::Type type,
|
||||
QRhiBuffer::UsageFlags usage,
|
||||
quint32 size) override;
|
||||
QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount,
|
||||
QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint) override;
|
||||
QRhiTexture *createTexture(QRhiTexture::Format format,
|
||||
const QSize &pixelSize,
|
||||
int depth,
|
||||
int arraySize,
|
||||
int sampleCount,
|
||||
QRhiTexture::Flags flags) override;
|
||||
QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
|
||||
QRhiSampler::Filter minFilter,
|
||||
QRhiSampler::Filter mipmapMode,
|
||||
QRhiSampler:: AddressMode u,
|
||||
QRhiSampler::AddressMode v,
|
||||
QRhiSampler::AddressMode w) override;
|
||||
|
||||
QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
|
||||
QRhiTextureRenderTarget::Flags flags) override;
|
||||
|
||||
QRhiSwapChain *createSwapChain() override;
|
||||
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
|
||||
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
|
||||
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
|
||||
QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
|
||||
QRhi::FrameOpResult finish() override;
|
||||
|
||||
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||
|
||||
void beginPass(QRhiCommandBuffer *cb,
|
||||
QRhiRenderTarget *rt,
|
||||
const QColor &colorClearValue,
|
||||
const QRhiDepthStencilClearValue &depthStencilClearValue,
|
||||
QRhiResourceUpdateBatch *resourceUpdates,
|
||||
QRhiCommandBuffer::BeginPassFlags flags) override;
|
||||
void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||
|
||||
void setGraphicsPipeline(QRhiCommandBuffer *cb,
|
||||
QRhiGraphicsPipeline *ps) override;
|
||||
|
||||
void setShaderResources(QRhiCommandBuffer *cb,
|
||||
QRhiShaderResourceBindings *srb,
|
||||
int dynamicOffsetCount,
|
||||
const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
|
||||
|
||||
void setVertexInput(QRhiCommandBuffer *cb,
|
||||
int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
|
||||
QRhiBuffer *indexBuf, quint32 indexOffset,
|
||||
QRhiCommandBuffer::IndexFormat indexFormat) override;
|
||||
|
||||
void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
|
||||
void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
|
||||
void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
|
||||
void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
|
||||
|
||||
void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
|
||||
quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
|
||||
|
||||
void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
|
||||
quint32 instanceCount, quint32 firstIndex,
|
||||
qint32 vertexOffset, quint32 firstInstance) override;
|
||||
|
||||
void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
|
||||
void debugMarkEnd(QRhiCommandBuffer *cb) override;
|
||||
void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
|
||||
|
||||
void beginComputePass(QRhiCommandBuffer *cb,
|
||||
QRhiResourceUpdateBatch *resourceUpdates,
|
||||
QRhiCommandBuffer::BeginPassFlags flags) override;
|
||||
void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||
void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
|
||||
void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;
|
||||
|
||||
const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
|
||||
void beginExternal(QRhiCommandBuffer *cb) override;
|
||||
void endExternal(QRhiCommandBuffer *cb) override;
|
||||
double lastCompletedGpuTime(QRhiCommandBuffer *cb) override;
|
||||
|
||||
QList<int> supportedSampleCounts() const override;
|
||||
int ubufAlignment() const override;
|
||||
bool isYUpInFramebuffer() const override;
|
||||
bool isYUpInNDC() const override;
|
||||
bool isClipDepthZeroToOne() const override;
|
||||
QMatrix4x4 clipSpaceCorrMatrix() const override;
|
||||
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
|
||||
bool isFeatureSupported(QRhi::Feature feature) const override;
|
||||
int resourceLimit(QRhi::ResourceLimit limit) const override;
|
||||
const QRhiNativeHandles *nativeHandles() override;
|
||||
QRhiDriverInfo driverInfo() const override;
|
||||
QRhiStats statistics() override;
|
||||
bool makeThreadLocalNativeContextCurrent() override;
|
||||
void releaseCachedResources() override;
|
||||
bool isDeviceLost() const override;
|
||||
|
||||
QByteArray pipelineCacheData() override;
|
||||
void setPipelineCacheData(const QByteArray &data) override;
|
||||
|
||||
void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD,
|
||||
int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc);
|
||||
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
|
||||
void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
|
||||
const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[]);
|
||||
void executeBufferHostWrites(QD3D11Buffer *bufD);
|
||||
void bindShaderResources(QD3D11ShaderResourceBindings *srbD,
|
||||
const uint *dynOfsPairs, int dynOfsPairCount,
|
||||
bool offsetOnlyChange);
|
||||
void resetShaderResources();
|
||||
void executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain = nullptr);
|
||||
DXGI_SAMPLE_DESC effectiveSampleCount(int sampleCount) const;
|
||||
void finishActiveReadbacks();
|
||||
void reportLiveObjects(ID3D11Device *device);
|
||||
void clearShaderCache();
|
||||
QByteArray compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, uint flags,
|
||||
QString *error, QShaderKey *usedShaderKey);
|
||||
bool ensureDirectCompositionDevice();
|
||||
|
||||
QRhi::Flags rhiFlags;
|
||||
bool debugLayer = false;
|
||||
bool importedDeviceAndContext = false;
|
||||
ID3D11Device *dev = nullptr;
|
||||
ID3D11DeviceContext1 *context = nullptr;
|
||||
D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL(0);
|
||||
LUID adapterLuid = {};
|
||||
ID3DUserDefinedAnnotation *annotations = nullptr;
|
||||
IDXGIAdapter1 *activeAdapter = nullptr;
|
||||
IDXGIFactory1 *dxgiFactory = nullptr;
|
||||
IDCompositionDevice *dcompDevice = nullptr;
|
||||
bool supportsAllowTearing = false;
|
||||
bool deviceLost = false;
|
||||
QRhiD3D11NativeHandles nativeHandlesStruct;
|
||||
QRhiDriverInfo driverInfoStruct;
|
||||
|
||||
struct {
|
||||
int vsHighestActiveVertexBufferBinding = -1;
|
||||
bool vsHasIndexBufferBound = false;
|
||||
int vsHighestActiveSrvBinding = -1;
|
||||
int hsHighestActiveSrvBinding = -1;
|
||||
int dsHighestActiveSrvBinding = -1;
|
||||
int gsHighestActiveSrvBinding = -1;
|
||||
int fsHighestActiveSrvBinding = -1;
|
||||
int csHighestActiveSrvBinding = -1;
|
||||
int csHighestActiveUavBinding = -1;
|
||||
QD3D11SwapChain *currentSwapChain = nullptr;
|
||||
} contextState;
|
||||
|
||||
struct OffscreenFrame {
|
||||
OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { }
|
||||
bool active = false;
|
||||
QD3D11CommandBuffer cbWrapper;
|
||||
QD3D11Timestamps timestamps;
|
||||
int timestampIdx = 0;
|
||||
} ofr;
|
||||
|
||||
struct TextureReadback {
|
||||
QRhiReadbackDescription desc;
|
||||
QRhiReadbackResult *result;
|
||||
ID3D11Texture2D *stagingTex;
|
||||
quint32 byteSize;
|
||||
quint32 bpl;
|
||||
QSize pixelSize;
|
||||
QRhiTexture::Format format;
|
||||
};
|
||||
QVarLengthArray<TextureReadback, 2> activeTextureReadbacks;
|
||||
struct BufferReadback {
|
||||
QRhiReadbackResult *result;
|
||||
quint32 byteSize;
|
||||
ID3D11Buffer *stagingBuf;
|
||||
};
|
||||
QVarLengthArray<BufferReadback, 2> activeBufferReadbacks;
|
||||
|
||||
struct Shader {
|
||||
Shader() = default;
|
||||
Shader(IUnknown *s, const QByteArray &bytecode, const QShader::NativeResourceBindingMap &rbm)
|
||||
: s(s), bytecode(bytecode), nativeResourceBindingMap(rbm) { }
|
||||
IUnknown *s;
|
||||
QByteArray bytecode;
|
||||
QShader::NativeResourceBindingMap nativeResourceBindingMap;
|
||||
};
|
||||
QHash<QRhiShaderStage, Shader> m_shaderCache;
|
||||
|
||||
// This is what gets exposed as the "pipeline cache", not that that concept
|
||||
// applies anyway. Here we are just storing the DX bytecode for a shader so
|
||||
// we can skip the HLSL->DXBC compilation when the QShader has HLSL source
|
||||
// code and the same shader source has already been compiled before.
|
||||
// m_shaderCache seemingly does the same, but this here does not care about
|
||||
// the ID3D11*Shader, this is just about the bytecode and about allowing
|
||||
// the data to be serialized to persistent storage and then reloaded in
|
||||
// future runs of the app, or when creating another QRhi, etc.
|
||||
struct BytecodeCacheKey {
|
||||
QByteArray sourceHash;
|
||||
QByteArray target;
|
||||
QByteArray entryPoint;
|
||||
uint compileFlags;
|
||||
};
|
||||
QHash<BytecodeCacheKey, QByteArray> m_bytecodeCache;
|
||||
};
|
||||
|
||||
Q_DECLARE_TYPEINFO(QRhiD3D11::TextureReadback, Q_RELOCATABLE_TYPE);
|
||||
Q_DECLARE_TYPEINFO(QRhiD3D11::BufferReadback, Q_RELOCATABLE_TYPE);
|
||||
|
||||
inline bool operator==(const QRhiD3D11::BytecodeCacheKey &a, const QRhiD3D11::BytecodeCacheKey &b) noexcept
|
||||
{
|
||||
return a.sourceHash == b.sourceHash
|
||||
&& a.target == b.target
|
||||
&& a.entryPoint == b.entryPoint
|
||||
&& a.compileFlags == b.compileFlags;
|
||||
}
|
||||
|
||||
inline bool operator!=(const QRhiD3D11::BytecodeCacheKey &a, const QRhiD3D11::BytecodeCacheKey &b) noexcept
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
inline size_t qHash(const QRhiD3D11::BytecodeCacheKey &k, size_t seed = 0) noexcept
|
||||
{
|
||||
return qHash(k.sourceHash, seed) ^ qHash(k.target) ^ qHash(k.entryPoint) ^ k.compileFlags;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
@ -1,853 +0,0 @@
|
||||
// Copyright (C) 2019 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QRHID3D11_P_H
|
||||
#define QRHID3D11_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "qrhid3d11_p.h"
|
||||
#include "qrhi_p_p.h"
|
||||
#include "qshaderdescription_p.h"
|
||||
#include <QWindow>
|
||||
|
||||
#include <d3d11_1.h>
|
||||
#include <dxgi1_6.h>
|
||||
#include <dcomp.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QRhiD3D11;
|
||||
|
||||
struct QD3D11Buffer : public QRhiBuffer
|
||||
{
|
||||
QD3D11Buffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size);
|
||||
~QD3D11Buffer();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
QRhiBuffer::NativeBuffer nativeBuffer() override;
|
||||
char *beginFullDynamicBufferUpdateForCurrentFrame() override;
|
||||
void endFullDynamicBufferUpdateForCurrentFrame() override;
|
||||
|
||||
ID3D11UnorderedAccessView *unorderedAccessView(quint32 offset);
|
||||
|
||||
ID3D11Buffer *buffer = nullptr;
|
||||
char *dynBuf = nullptr;
|
||||
bool hasPendingDynamicUpdates = false;
|
||||
QHash<quint32, ID3D11UnorderedAccessView *> uavs;
|
||||
uint generation = 0;
|
||||
friend class QRhiD3D11;
|
||||
};
|
||||
|
||||
struct QD3D11RenderBuffer : public QRhiRenderBuffer
|
||||
{
|
||||
QD3D11RenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint);
|
||||
~QD3D11RenderBuffer();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
QRhiTexture::Format backingFormat() const override;
|
||||
|
||||
ID3D11Texture2D *tex = nullptr;
|
||||
ID3D11DepthStencilView *dsv = nullptr;
|
||||
ID3D11RenderTargetView *rtv = nullptr;
|
||||
DXGI_FORMAT dxgiFormat;
|
||||
DXGI_SAMPLE_DESC sampleDesc;
|
||||
uint generation = 0;
|
||||
friend class QRhiD3D11;
|
||||
};
|
||||
|
||||
struct QD3D11Texture : public QRhiTexture
|
||||
{
|
||||
QD3D11Texture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
|
||||
int arraySize, int sampleCount, Flags flags);
|
||||
~QD3D11Texture();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
bool createFrom(NativeTexture src) override;
|
||||
NativeTexture nativeTexture() override;
|
||||
|
||||
bool prepareCreate(QSize *adjustedSize = nullptr);
|
||||
bool finishCreate();
|
||||
ID3D11UnorderedAccessView *unorderedAccessViewForLevel(int level);
|
||||
ID3D11Resource *textureResource() const
|
||||
{
|
||||
if (tex)
|
||||
return tex;
|
||||
else if (tex1D)
|
||||
return tex1D;
|
||||
return tex3D;
|
||||
}
|
||||
|
||||
ID3D11Texture2D *tex = nullptr;
|
||||
ID3D11Texture3D *tex3D = nullptr;
|
||||
ID3D11Texture1D *tex1D = nullptr;
|
||||
bool owns = true;
|
||||
ID3D11ShaderResourceView *srv = nullptr;
|
||||
DXGI_FORMAT dxgiFormat;
|
||||
uint mipLevelCount = 0;
|
||||
DXGI_SAMPLE_DESC sampleDesc;
|
||||
ID3D11UnorderedAccessView *perLevelViews[QRhi::MAX_MIP_LEVELS];
|
||||
uint generation = 0;
|
||||
friend class QRhiD3D11;
|
||||
};
|
||||
|
||||
struct QD3D11Sampler : public QRhiSampler
|
||||
{
|
||||
QD3D11Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
|
||||
AddressMode u, AddressMode v, AddressMode w);
|
||||
~QD3D11Sampler();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
|
||||
ID3D11SamplerState *samplerState = nullptr;
|
||||
uint generation = 0;
|
||||
friend class QRhiD3D11;
|
||||
};
|
||||
|
||||
struct QD3D11RenderPassDescriptor : public QRhiRenderPassDescriptor
|
||||
{
|
||||
QD3D11RenderPassDescriptor(QRhiImplementation *rhi);
|
||||
~QD3D11RenderPassDescriptor();
|
||||
void destroy() override;
|
||||
bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
|
||||
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
|
||||
QVector<quint32> serializedFormat() const override;
|
||||
};
|
||||
|
||||
struct QD3D11RenderTargetData
|
||||
{
|
||||
QD3D11RenderTargetData(QRhiImplementation *)
|
||||
{
|
||||
for (int i = 0; i < MAX_COLOR_ATTACHMENTS; ++i)
|
||||
rtv[i] = nullptr;
|
||||
}
|
||||
|
||||
QD3D11RenderPassDescriptor *rp = nullptr;
|
||||
QSize pixelSize;
|
||||
float dpr = 1;
|
||||
int sampleCount = 1;
|
||||
int colorAttCount = 0;
|
||||
int dsAttCount = 0;
|
||||
|
||||
static const int MAX_COLOR_ATTACHMENTS = 8;
|
||||
ID3D11RenderTargetView *rtv[MAX_COLOR_ATTACHMENTS];
|
||||
ID3D11DepthStencilView *dsv = nullptr;
|
||||
|
||||
QRhiRenderTargetAttachmentTracker::ResIdList currentResIdList;
|
||||
};
|
||||
|
||||
struct QD3D11SwapChainRenderTarget : public QRhiSwapChainRenderTarget
|
||||
{
|
||||
QD3D11SwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain);
|
||||
~QD3D11SwapChainRenderTarget();
|
||||
void destroy() override;
|
||||
|
||||
QSize pixelSize() const override;
|
||||
float devicePixelRatio() const override;
|
||||
int sampleCount() const override;
|
||||
|
||||
QD3D11RenderTargetData d;
|
||||
};
|
||||
|
||||
struct QD3D11TextureRenderTarget : public QRhiTextureRenderTarget
|
||||
{
|
||||
QD3D11TextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
|
||||
~QD3D11TextureRenderTarget();
|
||||
void destroy() override;
|
||||
|
||||
QSize pixelSize() const override;
|
||||
float devicePixelRatio() const override;
|
||||
int sampleCount() const override;
|
||||
|
||||
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
|
||||
bool create() override;
|
||||
|
||||
QD3D11RenderTargetData d;
|
||||
bool ownsRtv[QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS];
|
||||
ID3D11RenderTargetView *rtv[QD3D11RenderTargetData::MAX_COLOR_ATTACHMENTS];
|
||||
bool ownsDsv = false;
|
||||
ID3D11DepthStencilView *dsv = nullptr;
|
||||
friend class QRhiD3D11;
|
||||
};
|
||||
|
||||
struct QD3D11ShaderResourceBindings : public QRhiShaderResourceBindings
|
||||
{
|
||||
QD3D11ShaderResourceBindings(QRhiImplementation *rhi);
|
||||
~QD3D11ShaderResourceBindings();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
void updateResources(UpdateFlags flags) override;
|
||||
|
||||
bool hasDynamicOffset = false;
|
||||
QVarLengthArray<QRhiShaderResourceBinding, 8> sortedBindings;
|
||||
uint generation = 0;
|
||||
|
||||
// Keep track of the generation number of each referenced QRhi* to be able
|
||||
// to detect that the batched bindings are out of date.
|
||||
struct BoundUniformBufferData {
|
||||
quint64 id;
|
||||
uint generation;
|
||||
};
|
||||
struct BoundSampledTextureData {
|
||||
int count;
|
||||
struct {
|
||||
quint64 texId;
|
||||
uint texGeneration;
|
||||
quint64 samplerId;
|
||||
uint samplerGeneration;
|
||||
} d[QRhiShaderResourceBinding::Data::MAX_TEX_SAMPLER_ARRAY_SIZE];
|
||||
};
|
||||
struct BoundStorageImageData {
|
||||
quint64 id;
|
||||
uint generation;
|
||||
};
|
||||
struct BoundStorageBufferData {
|
||||
quint64 id;
|
||||
uint generation;
|
||||
};
|
||||
struct BoundResourceData {
|
||||
union {
|
||||
BoundUniformBufferData ubuf;
|
||||
BoundSampledTextureData stex;
|
||||
BoundStorageImageData simage;
|
||||
BoundStorageBufferData sbuf;
|
||||
};
|
||||
};
|
||||
QVarLengthArray<BoundResourceData, 8> boundResourceData;
|
||||
|
||||
struct StageUniformBufferBatches {
|
||||
bool present = false;
|
||||
QRhiBatchedBindings<ID3D11Buffer *> ubufs;
|
||||
QRhiBatchedBindings<UINT> ubuforigbindings;
|
||||
QRhiBatchedBindings<UINT> ubufoffsets;
|
||||
QRhiBatchedBindings<UINT> ubufsizes;
|
||||
void finish() {
|
||||
present = ubufs.finish();
|
||||
ubuforigbindings.finish();
|
||||
ubufoffsets.finish();
|
||||
ubufsizes.finish();
|
||||
}
|
||||
void clear() {
|
||||
ubufs.clear();
|
||||
ubuforigbindings.clear();
|
||||
ubufoffsets.clear();
|
||||
ubufsizes.clear();
|
||||
}
|
||||
};
|
||||
|
||||
struct StageSamplerBatches {
|
||||
bool present = false;
|
||||
QRhiBatchedBindings<ID3D11SamplerState *> samplers;
|
||||
QRhiBatchedBindings<ID3D11ShaderResourceView *> shaderresources;
|
||||
void finish() {
|
||||
present = samplers.finish();
|
||||
shaderresources.finish();
|
||||
}
|
||||
void clear() {
|
||||
samplers.clear();
|
||||
shaderresources.clear();
|
||||
}
|
||||
};
|
||||
|
||||
struct StageUavBatches {
|
||||
bool present = false;
|
||||
QRhiBatchedBindings<ID3D11UnorderedAccessView *> uavs;
|
||||
void finish() {
|
||||
present = uavs.finish();
|
||||
}
|
||||
void clear() {
|
||||
uavs.clear();
|
||||
}
|
||||
};
|
||||
|
||||
StageUniformBufferBatches vsUniformBufferBatches;
|
||||
StageUniformBufferBatches hsUniformBufferBatches;
|
||||
StageUniformBufferBatches dsUniformBufferBatches;
|
||||
StageUniformBufferBatches gsUniformBufferBatches;
|
||||
StageUniformBufferBatches fsUniformBufferBatches;
|
||||
StageUniformBufferBatches csUniformBufferBatches;
|
||||
|
||||
StageSamplerBatches vsSamplerBatches;
|
||||
StageSamplerBatches hsSamplerBatches;
|
||||
StageSamplerBatches dsSamplerBatches;
|
||||
StageSamplerBatches gsSamplerBatches;
|
||||
StageSamplerBatches fsSamplerBatches;
|
||||
StageSamplerBatches csSamplerBatches;
|
||||
|
||||
StageUavBatches csUavBatches;
|
||||
|
||||
friend class QRhiD3D11;
|
||||
};
|
||||
|
||||
Q_DECLARE_TYPEINFO(QD3D11ShaderResourceBindings::BoundResourceData, Q_RELOCATABLE_TYPE);
|
||||
|
||||
struct QD3D11GraphicsPipeline : public QRhiGraphicsPipeline
|
||||
{
|
||||
QD3D11GraphicsPipeline(QRhiImplementation *rhi);
|
||||
~QD3D11GraphicsPipeline();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
|
||||
ID3D11DepthStencilState *dsState = nullptr;
|
||||
ID3D11BlendState *blendState = nullptr;
|
||||
struct {
|
||||
ID3D11VertexShader *shader = nullptr;
|
||||
QShader::NativeResourceBindingMap nativeResourceBindingMap;
|
||||
} vs;
|
||||
struct {
|
||||
ID3D11HullShader *shader = nullptr;
|
||||
QShader::NativeResourceBindingMap nativeResourceBindingMap;
|
||||
} hs;
|
||||
struct {
|
||||
ID3D11DomainShader *shader = nullptr;
|
||||
QShader::NativeResourceBindingMap nativeResourceBindingMap;
|
||||
} ds;
|
||||
struct {
|
||||
ID3D11GeometryShader *shader = nullptr;
|
||||
QShader::NativeResourceBindingMap nativeResourceBindingMap;
|
||||
} gs;
|
||||
struct {
|
||||
ID3D11PixelShader *shader = nullptr;
|
||||
QShader::NativeResourceBindingMap nativeResourceBindingMap;
|
||||
} fs;
|
||||
ID3D11InputLayout *inputLayout = nullptr;
|
||||
D3D11_PRIMITIVE_TOPOLOGY d3dTopology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
||||
ID3D11RasterizerState *rastState = nullptr;
|
||||
uint generation = 0;
|
||||
friend class QRhiD3D11;
|
||||
};
|
||||
|
||||
struct QD3D11ComputePipeline : public QRhiComputePipeline
|
||||
{
|
||||
QD3D11ComputePipeline(QRhiImplementation *rhi);
|
||||
~QD3D11ComputePipeline();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
|
||||
struct {
|
||||
ID3D11ComputeShader *shader = nullptr;
|
||||
QShader::NativeResourceBindingMap nativeResourceBindingMap;
|
||||
} cs;
|
||||
uint generation = 0;
|
||||
friend class QRhiD3D11;
|
||||
};
|
||||
|
||||
struct QD3D11SwapChain;
|
||||
|
||||
struct QD3D11CommandBuffer : public QRhiCommandBuffer
|
||||
{
|
||||
QD3D11CommandBuffer(QRhiImplementation *rhi);
|
||||
~QD3D11CommandBuffer();
|
||||
void destroy() override;
|
||||
|
||||
// these must be kept at a reasonably low value otherwise sizeof Command explodes
|
||||
static const int MAX_DYNAMIC_OFFSET_COUNT = 8;
|
||||
static const int MAX_VERTEX_BUFFER_BINDING_COUNT = 8;
|
||||
|
||||
struct Command {
|
||||
enum Cmd {
|
||||
ResetShaderResources,
|
||||
SetRenderTarget,
|
||||
Clear,
|
||||
Viewport,
|
||||
Scissor,
|
||||
BindVertexBuffers,
|
||||
BindIndexBuffer,
|
||||
BindGraphicsPipeline,
|
||||
BindShaderResources,
|
||||
StencilRef,
|
||||
BlendConstants,
|
||||
Draw,
|
||||
DrawIndexed,
|
||||
UpdateSubRes,
|
||||
CopySubRes,
|
||||
ResolveSubRes,
|
||||
GenMip,
|
||||
DebugMarkBegin,
|
||||
DebugMarkEnd,
|
||||
DebugMarkMsg,
|
||||
BindComputePipeline,
|
||||
Dispatch
|
||||
};
|
||||
enum ClearFlag { Color = 1, Depth = 2, Stencil = 4 };
|
||||
Cmd cmd;
|
||||
|
||||
// QRhi*/QD3D11* references should be kept at minimum (so no
|
||||
// QRhiTexture/Buffer/etc. pointers).
|
||||
union Args {
|
||||
struct {
|
||||
QRhiRenderTarget *rt;
|
||||
} setRenderTarget;
|
||||
struct {
|
||||
QRhiRenderTarget *rt;
|
||||
int mask;
|
||||
float c[4];
|
||||
float d;
|
||||
quint32 s;
|
||||
} clear;
|
||||
struct {
|
||||
float x, y, w, h;
|
||||
float d0, d1;
|
||||
} viewport;
|
||||
struct {
|
||||
int x, y, w, h;
|
||||
} scissor;
|
||||
struct {
|
||||
int startSlot;
|
||||
int slotCount;
|
||||
ID3D11Buffer *buffers[MAX_VERTEX_BUFFER_BINDING_COUNT];
|
||||
UINT offsets[MAX_VERTEX_BUFFER_BINDING_COUNT];
|
||||
UINT strides[MAX_VERTEX_BUFFER_BINDING_COUNT];
|
||||
} bindVertexBuffers;
|
||||
struct {
|
||||
ID3D11Buffer *buffer;
|
||||
quint32 offset;
|
||||
DXGI_FORMAT format;
|
||||
} bindIndexBuffer;
|
||||
struct {
|
||||
QD3D11GraphicsPipeline *ps;
|
||||
} bindGraphicsPipeline;
|
||||
struct {
|
||||
QD3D11ShaderResourceBindings *srb;
|
||||
bool offsetOnlyChange;
|
||||
int dynamicOffsetCount;
|
||||
uint dynamicOffsetPairs[MAX_DYNAMIC_OFFSET_COUNT * 2]; // binding, offsetInConstants
|
||||
} bindShaderResources;
|
||||
struct {
|
||||
QD3D11GraphicsPipeline *ps;
|
||||
quint32 ref;
|
||||
} stencilRef;
|
||||
struct {
|
||||
QD3D11GraphicsPipeline *ps;
|
||||
float c[4];
|
||||
} blendConstants;
|
||||
struct {
|
||||
QD3D11GraphicsPipeline *ps;
|
||||
quint32 vertexCount;
|
||||
quint32 instanceCount;
|
||||
quint32 firstVertex;
|
||||
quint32 firstInstance;
|
||||
} draw;
|
||||
struct {
|
||||
QD3D11GraphicsPipeline *ps;
|
||||
quint32 indexCount;
|
||||
quint32 instanceCount;
|
||||
quint32 firstIndex;
|
||||
qint32 vertexOffset;
|
||||
quint32 firstInstance;
|
||||
} drawIndexed;
|
||||
struct {
|
||||
ID3D11Resource *dst;
|
||||
UINT dstSubRes;
|
||||
bool hasDstBox;
|
||||
D3D11_BOX dstBox;
|
||||
const void *src; // must come from retain*()
|
||||
UINT srcRowPitch;
|
||||
} updateSubRes;
|
||||
struct {
|
||||
ID3D11Resource *dst;
|
||||
UINT dstSubRes;
|
||||
UINT dstX;
|
||||
UINT dstY;
|
||||
UINT dstZ;
|
||||
ID3D11Resource *src;
|
||||
UINT srcSubRes;
|
||||
bool hasSrcBox;
|
||||
D3D11_BOX srcBox;
|
||||
} copySubRes;
|
||||
struct {
|
||||
ID3D11Resource *dst;
|
||||
UINT dstSubRes;
|
||||
ID3D11Resource *src;
|
||||
UINT srcSubRes;
|
||||
DXGI_FORMAT format;
|
||||
} resolveSubRes;
|
||||
struct {
|
||||
ID3D11ShaderResourceView *srv;
|
||||
} genMip;
|
||||
struct {
|
||||
char s[64];
|
||||
} debugMark;
|
||||
struct {
|
||||
QD3D11ComputePipeline *ps;
|
||||
} bindComputePipeline;
|
||||
struct {
|
||||
UINT x;
|
||||
UINT y;
|
||||
UINT z;
|
||||
} dispatch;
|
||||
} args;
|
||||
};
|
||||
|
||||
enum PassType {
|
||||
NoPass,
|
||||
RenderPass,
|
||||
ComputePass
|
||||
};
|
||||
|
||||
QRhiBackendCommandList<Command> commands;
|
||||
PassType recordingPass;
|
||||
double lastGpuTime = 0;
|
||||
QRhiRenderTarget *currentTarget;
|
||||
QRhiGraphicsPipeline *currentGraphicsPipeline;
|
||||
QRhiComputePipeline *currentComputePipeline;
|
||||
uint currentPipelineGeneration;
|
||||
QRhiShaderResourceBindings *currentGraphicsSrb;
|
||||
QRhiShaderResourceBindings *currentComputeSrb;
|
||||
uint currentSrbGeneration;
|
||||
ID3D11Buffer *currentIndexBuffer;
|
||||
quint32 currentIndexOffset;
|
||||
DXGI_FORMAT currentIndexFormat;
|
||||
ID3D11Buffer *currentVertexBuffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
|
||||
quint32 currentVertexOffsets[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
|
||||
|
||||
QVarLengthArray<QByteArray, 4> dataRetainPool;
|
||||
QVarLengthArray<QRhiBufferData, 4> bufferDataRetainPool;
|
||||
QVarLengthArray<QImage, 4> imageRetainPool;
|
||||
|
||||
// relies heavily on implicit sharing (no copies of the actual data will be made)
|
||||
const uchar *retainData(const QByteArray &data) {
|
||||
dataRetainPool.append(data);
|
||||
return reinterpret_cast<const uchar *>(dataRetainPool.last().constData());
|
||||
}
|
||||
const uchar *retainBufferData(const QRhiBufferData &data) {
|
||||
bufferDataRetainPool.append(data);
|
||||
return reinterpret_cast<const uchar *>(bufferDataRetainPool.last().constData());
|
||||
}
|
||||
const uchar *retainImage(const QImage &image) {
|
||||
imageRetainPool.append(image);
|
||||
return imageRetainPool.last().constBits();
|
||||
}
|
||||
void resetCommands() {
|
||||
commands.reset();
|
||||
dataRetainPool.clear();
|
||||
bufferDataRetainPool.clear();
|
||||
imageRetainPool.clear();
|
||||
}
|
||||
void resetState() {
|
||||
recordingPass = NoPass;
|
||||
// do not zero lastGpuTime
|
||||
currentTarget = nullptr;
|
||||
resetCommands();
|
||||
resetCachedState();
|
||||
}
|
||||
void resetCachedState() {
|
||||
currentGraphicsPipeline = nullptr;
|
||||
currentComputePipeline = nullptr;
|
||||
currentPipelineGeneration = 0;
|
||||
currentGraphicsSrb = nullptr;
|
||||
currentComputeSrb = nullptr;
|
||||
currentSrbGeneration = 0;
|
||||
currentIndexBuffer = nullptr;
|
||||
currentIndexOffset = 0;
|
||||
currentIndexFormat = DXGI_FORMAT_R16_UINT;
|
||||
memset(currentVertexBuffers, 0, sizeof(currentVertexBuffers));
|
||||
memset(currentVertexOffsets, 0, sizeof(currentVertexOffsets));
|
||||
}
|
||||
};
|
||||
|
||||
static const int QD3D11_SWAPCHAIN_BUFFER_COUNT = 2;
|
||||
|
||||
struct QD3D11Timestamps
|
||||
{
|
||||
static const int MAX_TIMESTAMP_PAIRS = QD3D11_SWAPCHAIN_BUFFER_COUNT;
|
||||
bool active[MAX_TIMESTAMP_PAIRS] = {};
|
||||
ID3D11Query *disjointQuery[MAX_TIMESTAMP_PAIRS] = {};
|
||||
ID3D11Query *query[MAX_TIMESTAMP_PAIRS * 2] = {};
|
||||
int pairCount = 0;
|
||||
|
||||
bool prepare(int pairCount, QRhiD3D11 *rhiD);
|
||||
void destroy();
|
||||
bool tryQueryTimestamps(int idx, ID3D11DeviceContext *context, double *elapsedSec);
|
||||
};
|
||||
|
||||
struct QD3D11SwapChain : public QRhiSwapChain
|
||||
{
|
||||
QD3D11SwapChain(QRhiImplementation *rhi);
|
||||
~QD3D11SwapChain();
|
||||
void destroy() override;
|
||||
|
||||
QRhiCommandBuffer *currentFrameCommandBuffer() override;
|
||||
QRhiRenderTarget *currentFrameRenderTarget() override;
|
||||
|
||||
QSize surfacePixelSize() override;
|
||||
bool isFormatSupported(Format f) override;
|
||||
QRhiSwapChainHdrInfo hdrInfo() override;
|
||||
|
||||
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
|
||||
bool createOrResize() override;
|
||||
|
||||
void releaseBuffers();
|
||||
bool newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc,
|
||||
ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv) const;
|
||||
|
||||
QWindow *window = nullptr;
|
||||
QSize pixelSize;
|
||||
QD3D11SwapChainRenderTarget rt;
|
||||
QD3D11CommandBuffer cb;
|
||||
DXGI_FORMAT colorFormat;
|
||||
DXGI_FORMAT srgbAdjustedColorFormat;
|
||||
IDXGISwapChain *swapChain = nullptr;
|
||||
UINT swapChainFlags = 0;
|
||||
ID3D11Texture2D *backBufferTex;
|
||||
ID3D11RenderTargetView *backBufferRtv;
|
||||
static const int BUFFER_COUNT = QD3D11_SWAPCHAIN_BUFFER_COUNT;
|
||||
ID3D11Texture2D *msaaTex[BUFFER_COUNT];
|
||||
ID3D11RenderTargetView *msaaRtv[BUFFER_COUNT];
|
||||
DXGI_SAMPLE_DESC sampleDesc;
|
||||
int currentFrameSlot = 0;
|
||||
int frameCount = 0;
|
||||
QD3D11RenderBuffer *ds = nullptr;
|
||||
UINT swapInterval = 1;
|
||||
IDCompositionTarget *dcompTarget = nullptr;
|
||||
IDCompositionVisual *dcompVisual = nullptr;
|
||||
QD3D11Timestamps timestamps;
|
||||
};
|
||||
|
||||
class QRhiD3D11 : public QRhiImplementation
|
||||
{
|
||||
public:
|
||||
QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importDevice = nullptr);
|
||||
|
||||
bool create(QRhi::Flags flags) override;
|
||||
void destroy() override;
|
||||
|
||||
QRhiGraphicsPipeline *createGraphicsPipeline() override;
|
||||
QRhiComputePipeline *createComputePipeline() override;
|
||||
QRhiShaderResourceBindings *createShaderResourceBindings() override;
|
||||
QRhiBuffer *createBuffer(QRhiBuffer::Type type,
|
||||
QRhiBuffer::UsageFlags usage,
|
||||
quint32 size) override;
|
||||
QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount,
|
||||
QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint) override;
|
||||
QRhiTexture *createTexture(QRhiTexture::Format format,
|
||||
const QSize &pixelSize,
|
||||
int depth,
|
||||
int arraySize,
|
||||
int sampleCount,
|
||||
QRhiTexture::Flags flags) override;
|
||||
QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
|
||||
QRhiSampler::Filter minFilter,
|
||||
QRhiSampler::Filter mipmapMode,
|
||||
QRhiSampler:: AddressMode u,
|
||||
QRhiSampler::AddressMode v,
|
||||
QRhiSampler::AddressMode w) override;
|
||||
|
||||
QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
|
||||
QRhiTextureRenderTarget::Flags flags) override;
|
||||
|
||||
QRhiSwapChain *createSwapChain() override;
|
||||
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
|
||||
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
|
||||
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
|
||||
QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
|
||||
QRhi::FrameOpResult finish() override;
|
||||
|
||||
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||
|
||||
void beginPass(QRhiCommandBuffer *cb,
|
||||
QRhiRenderTarget *rt,
|
||||
const QColor &colorClearValue,
|
||||
const QRhiDepthStencilClearValue &depthStencilClearValue,
|
||||
QRhiResourceUpdateBatch *resourceUpdates,
|
||||
QRhiCommandBuffer::BeginPassFlags flags) override;
|
||||
void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||
|
||||
void setGraphicsPipeline(QRhiCommandBuffer *cb,
|
||||
QRhiGraphicsPipeline *ps) override;
|
||||
|
||||
void setShaderResources(QRhiCommandBuffer *cb,
|
||||
QRhiShaderResourceBindings *srb,
|
||||
int dynamicOffsetCount,
|
||||
const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
|
||||
|
||||
void setVertexInput(QRhiCommandBuffer *cb,
|
||||
int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
|
||||
QRhiBuffer *indexBuf, quint32 indexOffset,
|
||||
QRhiCommandBuffer::IndexFormat indexFormat) override;
|
||||
|
||||
void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
|
||||
void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
|
||||
void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
|
||||
void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
|
||||
|
||||
void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
|
||||
quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
|
||||
|
||||
void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
|
||||
quint32 instanceCount, quint32 firstIndex,
|
||||
qint32 vertexOffset, quint32 firstInstance) override;
|
||||
|
||||
void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
|
||||
void debugMarkEnd(QRhiCommandBuffer *cb) override;
|
||||
void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
|
||||
|
||||
void beginComputePass(QRhiCommandBuffer *cb,
|
||||
QRhiResourceUpdateBatch *resourceUpdates,
|
||||
QRhiCommandBuffer::BeginPassFlags flags) override;
|
||||
void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||
void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
|
||||
void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;
|
||||
|
||||
const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
|
||||
void beginExternal(QRhiCommandBuffer *cb) override;
|
||||
void endExternal(QRhiCommandBuffer *cb) override;
|
||||
double lastCompletedGpuTime(QRhiCommandBuffer *cb) override;
|
||||
|
||||
QList<int> supportedSampleCounts() const override;
|
||||
int ubufAlignment() const override;
|
||||
bool isYUpInFramebuffer() const override;
|
||||
bool isYUpInNDC() const override;
|
||||
bool isClipDepthZeroToOne() const override;
|
||||
QMatrix4x4 clipSpaceCorrMatrix() const override;
|
||||
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
|
||||
bool isFeatureSupported(QRhi::Feature feature) const override;
|
||||
int resourceLimit(QRhi::ResourceLimit limit) const override;
|
||||
const QRhiNativeHandles *nativeHandles() override;
|
||||
QRhiDriverInfo driverInfo() const override;
|
||||
QRhiStats statistics() override;
|
||||
bool makeThreadLocalNativeContextCurrent() override;
|
||||
void releaseCachedResources() override;
|
||||
bool isDeviceLost() const override;
|
||||
|
||||
QByteArray pipelineCacheData() override;
|
||||
void setPipelineCacheData(const QByteArray &data) override;
|
||||
|
||||
void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD,
|
||||
int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc);
|
||||
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
|
||||
void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
|
||||
const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[]);
|
||||
void executeBufferHostWrites(QD3D11Buffer *bufD);
|
||||
void bindShaderResources(QD3D11ShaderResourceBindings *srbD,
|
||||
const uint *dynOfsPairs, int dynOfsPairCount,
|
||||
bool offsetOnlyChange);
|
||||
void resetShaderResources();
|
||||
void executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain = nullptr);
|
||||
DXGI_SAMPLE_DESC effectiveSampleCount(int sampleCount) const;
|
||||
void finishActiveReadbacks();
|
||||
void reportLiveObjects(ID3D11Device *device);
|
||||
void clearShaderCache();
|
||||
QByteArray compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, uint flags,
|
||||
QString *error, QShaderKey *usedShaderKey);
|
||||
bool ensureDirectCompositionDevice();
|
||||
|
||||
QRhi::Flags rhiFlags;
|
||||
bool debugLayer = false;
|
||||
bool importedDeviceAndContext = false;
|
||||
ID3D11Device *dev = nullptr;
|
||||
ID3D11DeviceContext1 *context = nullptr;
|
||||
D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL(0);
|
||||
LUID adapterLuid = {};
|
||||
ID3DUserDefinedAnnotation *annotations = nullptr;
|
||||
IDXGIAdapter1 *activeAdapter = nullptr;
|
||||
IDXGIFactory1 *dxgiFactory = nullptr;
|
||||
IDCompositionDevice *dcompDevice = nullptr;
|
||||
bool supportsAllowTearing = false;
|
||||
bool deviceLost = false;
|
||||
QRhiD3D11NativeHandles nativeHandlesStruct;
|
||||
QRhiDriverInfo driverInfoStruct;
|
||||
|
||||
struct {
|
||||
int vsHighestActiveVertexBufferBinding = -1;
|
||||
bool vsHasIndexBufferBound = false;
|
||||
int vsHighestActiveSrvBinding = -1;
|
||||
int hsHighestActiveSrvBinding = -1;
|
||||
int dsHighestActiveSrvBinding = -1;
|
||||
int gsHighestActiveSrvBinding = -1;
|
||||
int fsHighestActiveSrvBinding = -1;
|
||||
int csHighestActiveSrvBinding = -1;
|
||||
int csHighestActiveUavBinding = -1;
|
||||
QD3D11SwapChain *currentSwapChain = nullptr;
|
||||
} contextState;
|
||||
|
||||
struct OffscreenFrame {
|
||||
OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { }
|
||||
bool active = false;
|
||||
QD3D11CommandBuffer cbWrapper;
|
||||
QD3D11Timestamps timestamps;
|
||||
int timestampIdx = 0;
|
||||
} ofr;
|
||||
|
||||
struct TextureReadback {
|
||||
QRhiReadbackDescription desc;
|
||||
QRhiReadbackResult *result;
|
||||
ID3D11Texture2D *stagingTex;
|
||||
quint32 byteSize;
|
||||
quint32 bpl;
|
||||
QSize pixelSize;
|
||||
QRhiTexture::Format format;
|
||||
};
|
||||
QVarLengthArray<TextureReadback, 2> activeTextureReadbacks;
|
||||
struct BufferReadback {
|
||||
QRhiReadbackResult *result;
|
||||
quint32 byteSize;
|
||||
ID3D11Buffer *stagingBuf;
|
||||
};
|
||||
QVarLengthArray<BufferReadback, 2> activeBufferReadbacks;
|
||||
|
||||
struct Shader {
|
||||
Shader() = default;
|
||||
Shader(IUnknown *s, const QByteArray &bytecode, const QShader::NativeResourceBindingMap &rbm)
|
||||
: s(s), bytecode(bytecode), nativeResourceBindingMap(rbm) { }
|
||||
IUnknown *s;
|
||||
QByteArray bytecode;
|
||||
QShader::NativeResourceBindingMap nativeResourceBindingMap;
|
||||
};
|
||||
QHash<QRhiShaderStage, Shader> m_shaderCache;
|
||||
|
||||
// This is what gets exposed as the "pipeline cache", not that that concept
|
||||
// applies anyway. Here we are just storing the DX bytecode for a shader so
|
||||
// we can skip the HLSL->DXBC compilation when the QShader has HLSL source
|
||||
// code and the same shader source has already been compiled before.
|
||||
// m_shaderCache seemingly does the same, but this here does not care about
|
||||
// the ID3D11*Shader, this is just about the bytecode and about allowing
|
||||
// the data to be serialized to persistent storage and then reloaded in
|
||||
// future runs of the app, or when creating another QRhi, etc.
|
||||
struct BytecodeCacheKey {
|
||||
QByteArray sourceHash;
|
||||
QByteArray target;
|
||||
QByteArray entryPoint;
|
||||
uint compileFlags;
|
||||
};
|
||||
QHash<BytecodeCacheKey, QByteArray> m_bytecodeCache;
|
||||
};
|
||||
|
||||
Q_DECLARE_TYPEINFO(QRhiD3D11::TextureReadback, Q_RELOCATABLE_TYPE);
|
||||
Q_DECLARE_TYPEINFO(QRhiD3D11::BufferReadback, Q_RELOCATABLE_TYPE);
|
||||
|
||||
inline bool operator==(const QRhiD3D11::BytecodeCacheKey &a, const QRhiD3D11::BytecodeCacheKey &b) noexcept
|
||||
{
|
||||
return a.sourceHash == b.sourceHash
|
||||
&& a.target == b.target
|
||||
&& a.entryPoint == b.entryPoint
|
||||
&& a.compileFlags == b.compileFlags;
|
||||
}
|
||||
|
||||
inline bool operator!=(const QRhiD3D11::BytecodeCacheKey &a, const QRhiD3D11::BytecodeCacheKey &b) noexcept
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
inline size_t qHash(const QRhiD3D11::BytecodeCacheKey &k, size_t seed = 0) noexcept
|
||||
{
|
||||
return qHash(k.sourceHash, seed) ^ qHash(k.target) ^ qHash(k.entryPoint) ^ k.compileFlags;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
@ -1,8 +1,8 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include "qrhid3d12_p_p.h"
|
||||
#include "qshader_p.h"
|
||||
#include "qrhid3d12_p.h"
|
||||
#include "qshader.h"
|
||||
#include <QWindow>
|
||||
#include <qmath.h>
|
||||
#include <private/qsystemlibrary_p.h>
|
||||
@ -30,6 +30,9 @@ QT_BEGIN_NAMESPACE
|
||||
\inmodule QtGui
|
||||
\brief Direct3D 12 specific initialization parameters.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QRhi
|
||||
for details.
|
||||
|
||||
A D3D12-based QRhi needs no special parameters for initialization. If
|
||||
desired, enableDebugLayer can be set to \c true to enable the Direct3D
|
||||
debug layer. This can be useful during development, but should be avoided
|
||||
@ -62,16 +65,46 @@ QT_BEGIN_NAMESPACE
|
||||
commandQueue to a non-null value.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiD3D12InitParams::enableDebugLayer
|
||||
|
||||
When set to true, the debug layer is enabled, if installed and available.
|
||||
The default value is false.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QRhiD3D12NativeHandles
|
||||
\inmodule QtGui
|
||||
\brief Holds the D3D12 device used by the QRhi.
|
||||
|
||||
\note The class uses \c{void *} as the type since including the COM-based
|
||||
\c{d3d12.h} headers is not acceptable here. The actual type is
|
||||
\c{ID3D12Device *}.
|
||||
\c{d3d12.h} headers is not acceptable here. The actual types are
|
||||
\c{ID3D12Device *} and \c{ID3D12CommandQueue *}.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QRhi
|
||||
for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiD3D12NativeHandles::dev
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiD3D12NativeHandles::minimumFeatureLevel
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiD3D12NativeHandles::adapterLuidLow
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiD3D12NativeHandles::adapterLuidHigh
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiD3D12NativeHandles::commandQueue
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QRhiD3D12CommandBufferNativeHandles
|
||||
\inmodule QtGui
|
||||
@ -82,8 +115,15 @@ QT_BEGIN_NAMESPACE
|
||||
\l{QRhi::beginFrame()}{beginFrame()} - \l{QRhi::endFrame()}{endFrame()} or
|
||||
\l{QRhi::beginOffscreenFrame()}{beginOffscreenFrame()} -
|
||||
\l{QRhi::endOffscreenFrame()}{endOffscreenFrame()} pair.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QRhi
|
||||
for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiD3D12CommandBufferNativeHandles::commandList
|
||||
*/
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/direct3d12/hardware-feature-levels
|
||||
static const D3D_FEATURE_LEVEL MIN_FEATURE_LEVEL = D3D_FEATURE_LEVEL_11_0;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2021 The Qt Company Ltd.
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include "qrhigles2_p_p.h"
|
||||
#include "qrhigles2_p.h"
|
||||
#include <QOffscreenSurface>
|
||||
#include <QOpenGLContext>
|
||||
#include <QtCore/qmap.h>
|
||||
@ -27,10 +27,13 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QRhiGles2InitParams
|
||||
\internal
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
\brief OpenGL specific initialization parameters.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QRhi
|
||||
for details.
|
||||
|
||||
An OpenGL-based QRhi needs an already created QSurface that can be used in
|
||||
combination with QOpenGLContext. Most commonly, this is a QOffscreenSurface
|
||||
in practice. Additionally, while optional, it is recommended that the QWindow
|
||||
@ -103,13 +106,51 @@ QT_BEGIN_NAMESPACE
|
||||
QRhiGles2NativeHandles.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiGles2InitParams::format
|
||||
|
||||
The QSurfaceFormat, initialized to QSurfaceFormat::defaultFormat() by default.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiGles2InitParams::fallbackSurface
|
||||
|
||||
A QSurface compatible with \l format. Typically a QOffscreenSurface.
|
||||
Providing this is mandatory. Be aware of the threading implications: a
|
||||
QOffscreenSurface, like QWindow, must only ever be created and destroyed on
|
||||
the main (gui) thread, even if the QRhi is created and operates on another
|
||||
thread.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiGles2InitParams::window
|
||||
|
||||
Optional, but setting it is recommended when targeting a QWindow with the
|
||||
QRhi.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiGles2InitParams::shareContext
|
||||
|
||||
Optional, the QOpenGLContext to share resource with. QRhi creates its own
|
||||
context, and setting this member to a valid QOpenGLContext leads to calling
|
||||
\l{QOpenGLContext::setShareContext()}{setShareContext()} with it.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QRhiGles2NativeHandles
|
||||
\internal
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
\brief Holds the OpenGL context used by the QRhi.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QRhi
|
||||
for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiGles2NativeHandles::context
|
||||
*/
|
||||
|
||||
#ifndef GL_BGRA
|
||||
#define GL_BGRA 0x80E1
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,8 @@
|
||||
// Copyright (C) 2019 The Qt Company Ltd.
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include "qrhimetal_p_p.h"
|
||||
#include <QtGui/private/qshader_p_p.h>
|
||||
#include "qrhimetal_p.h"
|
||||
#include "qshader_p.h"
|
||||
#include <QGuiApplication>
|
||||
#include <QWindow>
|
||||
#include <QUrl>
|
||||
@ -50,9 +50,12 @@ QT_BEGIN_NAMESPACE
|
||||
/*!
|
||||
\class QRhiMetalInitParams
|
||||
\inmodule QtRhi
|
||||
\internal
|
||||
\since 6.6
|
||||
\brief Metal specific initialization parameters.
|
||||
|
||||
\note This an RHI API with limited compatibility guarantees, see \l QRhi
|
||||
for details.
|
||||
|
||||
A Metal-based QRhi needs no special parameters for initialization.
|
||||
|
||||
\badcode
|
||||
@ -85,14 +88,25 @@ QT_BEGIN_NAMESPACE
|
||||
/*!
|
||||
\class QRhiMetalNativeHandles
|
||||
\inmodule QtRhi
|
||||
\internal
|
||||
\since 6.6
|
||||
\brief Holds the Metal device used by the QRhi.
|
||||
|
||||
\note This an RHI API with limited compatibility guarantees, see \l QRhi
|
||||
for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiMetalNativeHandles::dev
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiMetalNativeHandles::cmdQueue
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QRhiMetalCommandBufferNativeHandles
|
||||
\inmodule QtRhi
|
||||
\internal
|
||||
\since 6.6
|
||||
\brief Holds the MTLCommandBuffer and MTLRenderCommandEncoder objects that are backing a QRhiCommandBuffer.
|
||||
|
||||
\note The command buffer object is only guaranteed to be valid while
|
||||
@ -104,8 +118,19 @@ QT_BEGIN_NAMESPACE
|
||||
\note The command encoder is only valid while recording a pass, that is,
|
||||
between \l{QRhiCommandBuffer::beginPass()} -
|
||||
\l{QRhiCommandBuffer::endPass()}.
|
||||
|
||||
\note This an RHI API with limited compatibility guarantees, see \l QRhi
|
||||
for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiMetalCommandBufferNativeHandles::commandBuffer
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiMetalCommandBufferNativeHandles::encoder
|
||||
*/
|
||||
|
||||
struct QMetalShader
|
||||
{
|
||||
id<MTLLibrary> lib = nil;
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Copyright (C) 2019 The Qt Company Ltd.
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QRHIMETAL_H
|
||||
#define QRHIMETAL_H
|
||||
#ifndef QRHIMETAL_P_H
|
||||
#define QRHIMETAL_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
@ -15,29 +15,493 @@
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <private/qrhi_p.h>
|
||||
|
||||
Q_FORWARD_DECLARE_OBJC_CLASS(MTLDevice);
|
||||
Q_FORWARD_DECLARE_OBJC_CLASS(MTLCommandQueue);
|
||||
Q_FORWARD_DECLARE_OBJC_CLASS(MTLCommandBuffer);
|
||||
Q_FORWARD_DECLARE_OBJC_CLASS(MTLRenderCommandEncoder);
|
||||
#include "qrhi_p.h"
|
||||
#include <QWindow>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
struct Q_GUI_EXPORT QRhiMetalInitParams : public QRhiInitParams
|
||||
static const int QMTL_FRAMES_IN_FLIGHT = 2;
|
||||
|
||||
// have to hide the ObjC stuff, this header cannot contain MTL* at all
|
||||
struct QMetalBufferData;
|
||||
|
||||
struct QMetalBuffer : public QRhiBuffer
|
||||
{
|
||||
QMetalBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size);
|
||||
~QMetalBuffer();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
QRhiBuffer::NativeBuffer nativeBuffer() override;
|
||||
char *beginFullDynamicBufferUpdateForCurrentFrame() override;
|
||||
void endFullDynamicBufferUpdateForCurrentFrame() override;
|
||||
|
||||
QMetalBufferData *d;
|
||||
uint generation = 0;
|
||||
int lastActiveFrameSlot = -1;
|
||||
friend class QRhiMetal;
|
||||
friend struct QMetalShaderResourceBindings;
|
||||
|
||||
static constexpr int WorkBufPoolUsage = 1 << 8;
|
||||
static_assert(WorkBufPoolUsage > QRhiBuffer::StorageBuffer);
|
||||
};
|
||||
|
||||
struct Q_GUI_EXPORT QRhiMetalNativeHandles : public QRhiNativeHandles
|
||||
struct QMetalRenderBufferData;
|
||||
|
||||
struct QMetalRenderBuffer : public QRhiRenderBuffer
|
||||
{
|
||||
MTLDevice *dev = nullptr;
|
||||
MTLCommandQueue *cmdQueue = nullptr;
|
||||
QMetalRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint);
|
||||
~QMetalRenderBuffer();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
QRhiTexture::Format backingFormat() const override;
|
||||
|
||||
QMetalRenderBufferData *d;
|
||||
int samples = 1;
|
||||
uint generation = 0;
|
||||
int lastActiveFrameSlot = -1;
|
||||
friend class QRhiMetal;
|
||||
};
|
||||
|
||||
struct Q_GUI_EXPORT QRhiMetalCommandBufferNativeHandles : public QRhiNativeHandles
|
||||
struct QMetalTextureData;
|
||||
|
||||
struct QMetalTexture : public QRhiTexture
|
||||
{
|
||||
MTLCommandBuffer *commandBuffer = nullptr;
|
||||
MTLRenderCommandEncoder *encoder = nullptr;
|
||||
QMetalTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
|
||||
int arraySize, int sampleCount, Flags flags);
|
||||
~QMetalTexture();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
bool createFrom(NativeTexture src) override;
|
||||
NativeTexture nativeTexture() override;
|
||||
|
||||
bool prepareCreate(QSize *adjustedSize = nullptr);
|
||||
|
||||
QMetalTextureData *d;
|
||||
int mipLevelCount = 0;
|
||||
int samples = 1;
|
||||
uint generation = 0;
|
||||
int lastActiveFrameSlot = -1;
|
||||
friend class QRhiMetal;
|
||||
friend struct QMetalShaderResourceBindings;
|
||||
friend struct QMetalTextureData;
|
||||
};
|
||||
|
||||
struct QMetalSamplerData;
|
||||
|
||||
struct QMetalSampler : public QRhiSampler
|
||||
{
|
||||
QMetalSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
|
||||
AddressMode u, AddressMode v, AddressMode w);
|
||||
~QMetalSampler();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
|
||||
QMetalSamplerData *d;
|
||||
uint generation = 0;
|
||||
int lastActiveFrameSlot = -1;
|
||||
friend class QRhiMetal;
|
||||
friend struct QMetalShaderResourceBindings;
|
||||
};
|
||||
|
||||
struct QMetalRenderPassDescriptor : public QRhiRenderPassDescriptor
|
||||
{
|
||||
QMetalRenderPassDescriptor(QRhiImplementation *rhi);
|
||||
~QMetalRenderPassDescriptor();
|
||||
void destroy() override;
|
||||
bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
|
||||
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
|
||||
QVector<quint32> serializedFormat() const override;
|
||||
|
||||
void updateSerializedFormat();
|
||||
|
||||
// there is no MTLRenderPassDescriptor here as one will be created for each pass in beginPass()
|
||||
|
||||
// but the things needed for the render pipeline descriptor have to be provided
|
||||
static const int MAX_COLOR_ATTACHMENTS = 8;
|
||||
int colorAttachmentCount = 0;
|
||||
bool hasDepthStencil = false;
|
||||
int colorFormat[MAX_COLOR_ATTACHMENTS];
|
||||
int dsFormat;
|
||||
QVector<quint32> serializedFormatData;
|
||||
};
|
||||
|
||||
struct QMetalRenderTargetData;
|
||||
|
||||
struct QMetalSwapChainRenderTarget : public QRhiSwapChainRenderTarget
|
||||
{
|
||||
QMetalSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain);
|
||||
~QMetalSwapChainRenderTarget();
|
||||
void destroy() override;
|
||||
|
||||
QSize pixelSize() const override;
|
||||
float devicePixelRatio() const override;
|
||||
int sampleCount() const override;
|
||||
|
||||
QMetalRenderTargetData *d;
|
||||
};
|
||||
|
||||
struct QMetalTextureRenderTarget : public QRhiTextureRenderTarget
|
||||
{
|
||||
QMetalTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
|
||||
~QMetalTextureRenderTarget();
|
||||
void destroy() override;
|
||||
|
||||
QSize pixelSize() const override;
|
||||
float devicePixelRatio() const override;
|
||||
int sampleCount() const override;
|
||||
|
||||
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
|
||||
bool create() override;
|
||||
|
||||
QMetalRenderTargetData *d;
|
||||
friend class QRhiMetal;
|
||||
};
|
||||
|
||||
struct QMetalShaderResourceBindings : public QRhiShaderResourceBindings
|
||||
{
|
||||
QMetalShaderResourceBindings(QRhiImplementation *rhi);
|
||||
~QMetalShaderResourceBindings();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
void updateResources(UpdateFlags flags) override;
|
||||
|
||||
QVarLengthArray<QRhiShaderResourceBinding, 8> sortedBindings;
|
||||
int maxBinding = -1;
|
||||
|
||||
struct BoundUniformBufferData {
|
||||
quint64 id;
|
||||
uint generation;
|
||||
};
|
||||
struct BoundSampledTextureData {
|
||||
int count;
|
||||
struct {
|
||||
quint64 texId;
|
||||
uint texGeneration;
|
||||
quint64 samplerId;
|
||||
uint samplerGeneration;
|
||||
} d[QRhiShaderResourceBinding::Data::MAX_TEX_SAMPLER_ARRAY_SIZE];
|
||||
};
|
||||
struct BoundStorageImageData {
|
||||
quint64 id;
|
||||
uint generation;
|
||||
};
|
||||
struct BoundStorageBufferData {
|
||||
quint64 id;
|
||||
uint generation;
|
||||
};
|
||||
struct BoundResourceData {
|
||||
union {
|
||||
BoundUniformBufferData ubuf;
|
||||
BoundSampledTextureData stex;
|
||||
BoundStorageImageData simage;
|
||||
BoundStorageBufferData sbuf;
|
||||
};
|
||||
};
|
||||
QVarLengthArray<BoundResourceData, 8> boundResourceData;
|
||||
|
||||
uint generation = 0;
|
||||
friend class QRhiMetal;
|
||||
};
|
||||
|
||||
struct QMetalGraphicsPipelineData;
|
||||
struct QMetalCommandBuffer;
|
||||
|
||||
struct QMetalGraphicsPipeline : public QRhiGraphicsPipeline
|
||||
{
|
||||
QMetalGraphicsPipeline(QRhiImplementation *rhi);
|
||||
~QMetalGraphicsPipeline();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
|
||||
void makeActiveForCurrentRenderPassEncoder(QMetalCommandBuffer *cbD);
|
||||
void setupAttachmentsInMetalRenderPassDescriptor(void *metalRpDesc, QMetalRenderPassDescriptor *rpD);
|
||||
void setupMetalDepthStencilDescriptor(void *metalDsDesc);
|
||||
void mapStates();
|
||||
bool createVertexFragmentPipeline();
|
||||
bool createTessellationPipelines(const QShader &tessVert, const QShader &tesc, const QShader &tese, const QShader &tessFrag);
|
||||
|
||||
QMetalGraphicsPipelineData *d;
|
||||
uint generation = 0;
|
||||
int lastActiveFrameSlot = -1;
|
||||
friend class QRhiMetal;
|
||||
};
|
||||
|
||||
struct QMetalComputePipelineData;
|
||||
|
||||
struct QMetalComputePipeline : public QRhiComputePipeline
|
||||
{
|
||||
QMetalComputePipeline(QRhiImplementation *rhi);
|
||||
~QMetalComputePipeline();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
|
||||
QMetalComputePipelineData *d;
|
||||
uint generation = 0;
|
||||
int lastActiveFrameSlot = -1;
|
||||
friend class QRhiMetal;
|
||||
};
|
||||
|
||||
struct QMetalCommandBufferData;
|
||||
struct QMetalSwapChain;
|
||||
|
||||
struct QMetalCommandBuffer : public QRhiCommandBuffer
|
||||
{
|
||||
QMetalCommandBuffer(QRhiImplementation *rhi);
|
||||
~QMetalCommandBuffer();
|
||||
void destroy() override;
|
||||
|
||||
QMetalCommandBufferData *d = nullptr;
|
||||
QRhiMetalCommandBufferNativeHandles nativeHandlesStruct;
|
||||
|
||||
enum PassType {
|
||||
NoPass,
|
||||
RenderPass,
|
||||
ComputePass
|
||||
};
|
||||
|
||||
// per-pass (render or compute command encoder) persistent state
|
||||
PassType recordingPass;
|
||||
QRhiRenderTarget *currentTarget;
|
||||
|
||||
// per-pass (render or compute command encoder) volatile (cached) state
|
||||
QMetalGraphicsPipeline *currentGraphicsPipeline;
|
||||
QMetalComputePipeline *currentComputePipeline;
|
||||
uint currentPipelineGeneration;
|
||||
QMetalShaderResourceBindings *currentGraphicsSrb;
|
||||
QMetalShaderResourceBindings *currentComputeSrb;
|
||||
uint currentSrbGeneration;
|
||||
int currentResSlot;
|
||||
QMetalBuffer *currentIndexBuffer;
|
||||
quint32 currentIndexOffset;
|
||||
QRhiCommandBuffer::IndexFormat currentIndexFormat;
|
||||
int currentCullMode;
|
||||
int currentTriangleFillMode;
|
||||
int currentFrontFaceWinding;
|
||||
QPair<float, float> currentDepthBiasValues;
|
||||
|
||||
const QRhiNativeHandles *nativeHandles();
|
||||
void resetState(double lastGpuTime = 0);
|
||||
void resetPerPassState();
|
||||
void resetPerPassCachedState();
|
||||
};
|
||||
|
||||
struct QMetalSwapChainData;
|
||||
|
||||
struct QMetalSwapChain : public QRhiSwapChain
|
||||
{
|
||||
QMetalSwapChain(QRhiImplementation *rhi);
|
||||
~QMetalSwapChain();
|
||||
void destroy() override;
|
||||
|
||||
QRhiCommandBuffer *currentFrameCommandBuffer() override;
|
||||
QRhiRenderTarget *currentFrameRenderTarget() override;
|
||||
QSize surfacePixelSize() override;
|
||||
bool isFormatSupported(Format f) override;
|
||||
|
||||
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
|
||||
|
||||
bool createOrResize() override;
|
||||
|
||||
virtual QRhiSwapChainHdrInfo hdrInfo() override;
|
||||
|
||||
void chooseFormats();
|
||||
void waitUntilCompleted(int slot);
|
||||
|
||||
QWindow *window = nullptr;
|
||||
QSize pixelSize;
|
||||
int currentFrameSlot = 0; // 0..QMTL_FRAMES_IN_FLIGHT-1
|
||||
int frameCount = 0;
|
||||
int samples = 1;
|
||||
QMetalSwapChainRenderTarget rtWrapper;
|
||||
QMetalCommandBuffer cbWrapper;
|
||||
QMetalRenderBuffer *ds = nullptr;
|
||||
QMetalSwapChainData *d = nullptr;
|
||||
};
|
||||
|
||||
struct QRhiMetalData;
|
||||
|
||||
class QRhiMetal : public QRhiImplementation
|
||||
{
|
||||
public:
|
||||
QRhiMetal(QRhiMetalInitParams *params, QRhiMetalNativeHandles *importDevice = nullptr);
|
||||
~QRhiMetal();
|
||||
|
||||
static bool probe(QRhiMetalInitParams *params);
|
||||
static QRhiSwapChainProxyData updateSwapChainProxyData(QWindow *window);
|
||||
|
||||
bool create(QRhi::Flags flags) override;
|
||||
void destroy() override;
|
||||
|
||||
QRhiGraphicsPipeline *createGraphicsPipeline() override;
|
||||
QRhiComputePipeline *createComputePipeline() override;
|
||||
QRhiShaderResourceBindings *createShaderResourceBindings() override;
|
||||
QRhiBuffer *createBuffer(QRhiBuffer::Type type,
|
||||
QRhiBuffer::UsageFlags usage,
|
||||
quint32 size) override;
|
||||
QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount,
|
||||
QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint) override;
|
||||
QRhiTexture *createTexture(QRhiTexture::Format format,
|
||||
const QSize &pixelSize,
|
||||
int depth,
|
||||
int arraySize,
|
||||
int sampleCount,
|
||||
QRhiTexture::Flags flags) override;
|
||||
QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
|
||||
QRhiSampler::Filter minFilter,
|
||||
QRhiSampler::Filter mipmapMode,
|
||||
QRhiSampler:: AddressMode u,
|
||||
QRhiSampler::AddressMode v,
|
||||
QRhiSampler::AddressMode w) override;
|
||||
|
||||
QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
|
||||
QRhiTextureRenderTarget::Flags flags) override;
|
||||
|
||||
QRhiSwapChain *createSwapChain() override;
|
||||
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
|
||||
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
|
||||
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
|
||||
QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
|
||||
QRhi::FrameOpResult finish() override;
|
||||
|
||||
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||
|
||||
void beginPass(QRhiCommandBuffer *cb,
|
||||
QRhiRenderTarget *rt,
|
||||
const QColor &colorClearValue,
|
||||
const QRhiDepthStencilClearValue &depthStencilClearValue,
|
||||
QRhiResourceUpdateBatch *resourceUpdates,
|
||||
QRhiCommandBuffer::BeginPassFlags flags) override;
|
||||
void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||
|
||||
void setGraphicsPipeline(QRhiCommandBuffer *cb,
|
||||
QRhiGraphicsPipeline *ps) override;
|
||||
|
||||
void setShaderResources(QRhiCommandBuffer *cb,
|
||||
QRhiShaderResourceBindings *srb,
|
||||
int dynamicOffsetCount,
|
||||
const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
|
||||
|
||||
void setVertexInput(QRhiCommandBuffer *cb,
|
||||
int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
|
||||
QRhiBuffer *indexBuf, quint32 indexOffset,
|
||||
QRhiCommandBuffer::IndexFormat indexFormat) override;
|
||||
|
||||
void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
|
||||
void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
|
||||
void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
|
||||
void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
|
||||
|
||||
void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
|
||||
quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
|
||||
|
||||
void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
|
||||
quint32 instanceCount, quint32 firstIndex,
|
||||
qint32 vertexOffset, quint32 firstInstance) override;
|
||||
|
||||
void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
|
||||
void debugMarkEnd(QRhiCommandBuffer *cb) override;
|
||||
void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
|
||||
|
||||
void beginComputePass(QRhiCommandBuffer *cb,
|
||||
QRhiResourceUpdateBatch *resourceUpdates,
|
||||
QRhiCommandBuffer::BeginPassFlags flags) override;
|
||||
void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||
void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
|
||||
void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;
|
||||
|
||||
const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
|
||||
void beginExternal(QRhiCommandBuffer *cb) override;
|
||||
void endExternal(QRhiCommandBuffer *cb) override;
|
||||
double lastCompletedGpuTime(QRhiCommandBuffer *cb) override;
|
||||
|
||||
QList<int> supportedSampleCounts() const override;
|
||||
int ubufAlignment() const override;
|
||||
bool isYUpInFramebuffer() const override;
|
||||
bool isYUpInNDC() const override;
|
||||
bool isClipDepthZeroToOne() const override;
|
||||
QMatrix4x4 clipSpaceCorrMatrix() const override;
|
||||
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
|
||||
bool isFeatureSupported(QRhi::Feature feature) const override;
|
||||
int resourceLimit(QRhi::ResourceLimit limit) const override;
|
||||
const QRhiNativeHandles *nativeHandles() override;
|
||||
QRhiDriverInfo driverInfo() const override;
|
||||
QRhiStats statistics() override;
|
||||
bool makeThreadLocalNativeContextCurrent() override;
|
||||
void releaseCachedResources() override;
|
||||
bool isDeviceLost() const override;
|
||||
|
||||
QByteArray pipelineCacheData() override;
|
||||
void setPipelineCacheData(const QByteArray &data) override;
|
||||
|
||||
void executeDeferredReleases(bool forced = false);
|
||||
void finishActiveReadbacks(bool forced = false);
|
||||
qsizetype subresUploadByteSize(const QRhiTextureSubresourceUploadDescription &subresDesc) const;
|
||||
void enqueueSubresUpload(QMetalTexture *texD, void *mp, void *blitEncPtr,
|
||||
int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc,
|
||||
qsizetype *curOfs);
|
||||
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
|
||||
void executeBufferHostWritesForSlot(QMetalBuffer *bufD, int slot);
|
||||
void executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD);
|
||||
static const int SUPPORTED_STAGES = 5;
|
||||
void enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD,
|
||||
QMetalCommandBuffer *cbD,
|
||||
int dynamicOffsetCount,
|
||||
const QRhiCommandBuffer::DynamicOffset *dynamicOffsets,
|
||||
bool offsetOnlyChange,
|
||||
const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[SUPPORTED_STAGES]);
|
||||
int effectiveSampleCount(int sampleCount) const;
|
||||
struct TessDrawArgs {
|
||||
QMetalCommandBuffer *cbD;
|
||||
enum {
|
||||
NonIndexed,
|
||||
U16Indexed,
|
||||
U32Indexed
|
||||
} type;
|
||||
struct NonIndexedArgs {
|
||||
quint32 vertexCount;
|
||||
quint32 instanceCount;
|
||||
quint32 firstVertex;
|
||||
quint32 firstInstance;
|
||||
};
|
||||
struct IndexedArgs {
|
||||
quint32 indexCount;
|
||||
quint32 instanceCount;
|
||||
quint32 firstIndex;
|
||||
qint32 vertexOffset;
|
||||
quint32 firstInstance;
|
||||
void *indexBuffer;
|
||||
};
|
||||
union {
|
||||
NonIndexedArgs draw;
|
||||
IndexedArgs drawIndexed;
|
||||
};
|
||||
};
|
||||
void tessellatedDraw(const TessDrawArgs &args);
|
||||
|
||||
QRhi::Flags rhiFlags;
|
||||
bool importedDevice = false;
|
||||
bool importedCmdQueue = false;
|
||||
QMetalSwapChain *currentSwapChain = nullptr;
|
||||
QSet<QMetalSwapChain *> swapchains;
|
||||
QRhiMetalNativeHandles nativeHandlesStruct;
|
||||
QRhiDriverInfo driverInfoStruct;
|
||||
quint32 osMajor = 0;
|
||||
quint32 osMinor = 0;
|
||||
|
||||
struct {
|
||||
int maxTextureSize = 4096;
|
||||
bool baseVertexAndInstance = true;
|
||||
QVector<int> supportedSampleCounts;
|
||||
bool isAppleGPU = false;
|
||||
int maxThreadGroupSize = 512;
|
||||
} caps;
|
||||
|
||||
QRhiMetalData *d = nullptr;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -1,510 +0,0 @@
|
||||
// Copyright (C) 2019 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QRHIMETAL_P_H
|
||||
#define QRHIMETAL_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "qrhimetal_p.h"
|
||||
#include "qrhi_p_p.h"
|
||||
#include <QWindow>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
static const int QMTL_FRAMES_IN_FLIGHT = 2;
|
||||
|
||||
// have to hide the ObjC stuff, this header cannot contain MTL* at all
|
||||
struct QMetalBufferData;
|
||||
|
||||
struct QMetalBuffer : public QRhiBuffer
|
||||
{
|
||||
QMetalBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size);
|
||||
~QMetalBuffer();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
QRhiBuffer::NativeBuffer nativeBuffer() override;
|
||||
char *beginFullDynamicBufferUpdateForCurrentFrame() override;
|
||||
void endFullDynamicBufferUpdateForCurrentFrame() override;
|
||||
|
||||
QMetalBufferData *d;
|
||||
uint generation = 0;
|
||||
int lastActiveFrameSlot = -1;
|
||||
friend class QRhiMetal;
|
||||
friend struct QMetalShaderResourceBindings;
|
||||
|
||||
static constexpr int WorkBufPoolUsage = 1 << 8;
|
||||
static_assert(WorkBufPoolUsage > QRhiBuffer::StorageBuffer);
|
||||
};
|
||||
|
||||
struct QMetalRenderBufferData;
|
||||
|
||||
struct QMetalRenderBuffer : public QRhiRenderBuffer
|
||||
{
|
||||
QMetalRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint);
|
||||
~QMetalRenderBuffer();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
QRhiTexture::Format backingFormat() const override;
|
||||
|
||||
QMetalRenderBufferData *d;
|
||||
int samples = 1;
|
||||
uint generation = 0;
|
||||
int lastActiveFrameSlot = -1;
|
||||
friend class QRhiMetal;
|
||||
};
|
||||
|
||||
struct QMetalTextureData;
|
||||
|
||||
struct QMetalTexture : public QRhiTexture
|
||||
{
|
||||
QMetalTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
|
||||
int arraySize, int sampleCount, Flags flags);
|
||||
~QMetalTexture();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
bool createFrom(NativeTexture src) override;
|
||||
NativeTexture nativeTexture() override;
|
||||
|
||||
bool prepareCreate(QSize *adjustedSize = nullptr);
|
||||
|
||||
QMetalTextureData *d;
|
||||
int mipLevelCount = 0;
|
||||
int samples = 1;
|
||||
uint generation = 0;
|
||||
int lastActiveFrameSlot = -1;
|
||||
friend class QRhiMetal;
|
||||
friend struct QMetalShaderResourceBindings;
|
||||
friend struct QMetalTextureData;
|
||||
};
|
||||
|
||||
struct QMetalSamplerData;
|
||||
|
||||
struct QMetalSampler : public QRhiSampler
|
||||
{
|
||||
QMetalSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
|
||||
AddressMode u, AddressMode v, AddressMode w);
|
||||
~QMetalSampler();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
|
||||
QMetalSamplerData *d;
|
||||
uint generation = 0;
|
||||
int lastActiveFrameSlot = -1;
|
||||
friend class QRhiMetal;
|
||||
friend struct QMetalShaderResourceBindings;
|
||||
};
|
||||
|
||||
struct QMetalRenderPassDescriptor : public QRhiRenderPassDescriptor
|
||||
{
|
||||
QMetalRenderPassDescriptor(QRhiImplementation *rhi);
|
||||
~QMetalRenderPassDescriptor();
|
||||
void destroy() override;
|
||||
bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
|
||||
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
|
||||
QVector<quint32> serializedFormat() const override;
|
||||
|
||||
void updateSerializedFormat();
|
||||
|
||||
// there is no MTLRenderPassDescriptor here as one will be created for each pass in beginPass()
|
||||
|
||||
// but the things needed for the render pipeline descriptor have to be provided
|
||||
static const int MAX_COLOR_ATTACHMENTS = 8;
|
||||
int colorAttachmentCount = 0;
|
||||
bool hasDepthStencil = false;
|
||||
int colorFormat[MAX_COLOR_ATTACHMENTS];
|
||||
int dsFormat;
|
||||
QVector<quint32> serializedFormatData;
|
||||
};
|
||||
|
||||
struct QMetalRenderTargetData;
|
||||
|
||||
struct QMetalSwapChainRenderTarget : public QRhiSwapChainRenderTarget
|
||||
{
|
||||
QMetalSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain);
|
||||
~QMetalSwapChainRenderTarget();
|
||||
void destroy() override;
|
||||
|
||||
QSize pixelSize() const override;
|
||||
float devicePixelRatio() const override;
|
||||
int sampleCount() const override;
|
||||
|
||||
QMetalRenderTargetData *d;
|
||||
};
|
||||
|
||||
struct QMetalTextureRenderTarget : public QRhiTextureRenderTarget
|
||||
{
|
||||
QMetalTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
|
||||
~QMetalTextureRenderTarget();
|
||||
void destroy() override;
|
||||
|
||||
QSize pixelSize() const override;
|
||||
float devicePixelRatio() const override;
|
||||
int sampleCount() const override;
|
||||
|
||||
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
|
||||
bool create() override;
|
||||
|
||||
QMetalRenderTargetData *d;
|
||||
friend class QRhiMetal;
|
||||
};
|
||||
|
||||
struct QMetalShaderResourceBindings : public QRhiShaderResourceBindings
|
||||
{
|
||||
QMetalShaderResourceBindings(QRhiImplementation *rhi);
|
||||
~QMetalShaderResourceBindings();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
void updateResources(UpdateFlags flags) override;
|
||||
|
||||
QVarLengthArray<QRhiShaderResourceBinding, 8> sortedBindings;
|
||||
int maxBinding = -1;
|
||||
|
||||
struct BoundUniformBufferData {
|
||||
quint64 id;
|
||||
uint generation;
|
||||
};
|
||||
struct BoundSampledTextureData {
|
||||
int count;
|
||||
struct {
|
||||
quint64 texId;
|
||||
uint texGeneration;
|
||||
quint64 samplerId;
|
||||
uint samplerGeneration;
|
||||
} d[QRhiShaderResourceBinding::Data::MAX_TEX_SAMPLER_ARRAY_SIZE];
|
||||
};
|
||||
struct BoundStorageImageData {
|
||||
quint64 id;
|
||||
uint generation;
|
||||
};
|
||||
struct BoundStorageBufferData {
|
||||
quint64 id;
|
||||
uint generation;
|
||||
};
|
||||
struct BoundResourceData {
|
||||
union {
|
||||
BoundUniformBufferData ubuf;
|
||||
BoundSampledTextureData stex;
|
||||
BoundStorageImageData simage;
|
||||
BoundStorageBufferData sbuf;
|
||||
};
|
||||
};
|
||||
QVarLengthArray<BoundResourceData, 8> boundResourceData;
|
||||
|
||||
uint generation = 0;
|
||||
friend class QRhiMetal;
|
||||
};
|
||||
|
||||
struct QMetalGraphicsPipelineData;
|
||||
struct QMetalCommandBuffer;
|
||||
|
||||
struct QMetalGraphicsPipeline : public QRhiGraphicsPipeline
|
||||
{
|
||||
QMetalGraphicsPipeline(QRhiImplementation *rhi);
|
||||
~QMetalGraphicsPipeline();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
|
||||
void makeActiveForCurrentRenderPassEncoder(QMetalCommandBuffer *cbD);
|
||||
void setupAttachmentsInMetalRenderPassDescriptor(void *metalRpDesc, QMetalRenderPassDescriptor *rpD);
|
||||
void setupMetalDepthStencilDescriptor(void *metalDsDesc);
|
||||
void mapStates();
|
||||
bool createVertexFragmentPipeline();
|
||||
bool createTessellationPipelines(const QShader &tessVert, const QShader &tesc, const QShader &tese, const QShader &tessFrag);
|
||||
|
||||
QMetalGraphicsPipelineData *d;
|
||||
uint generation = 0;
|
||||
int lastActiveFrameSlot = -1;
|
||||
friend class QRhiMetal;
|
||||
};
|
||||
|
||||
struct QMetalComputePipelineData;
|
||||
|
||||
struct QMetalComputePipeline : public QRhiComputePipeline
|
||||
{
|
||||
QMetalComputePipeline(QRhiImplementation *rhi);
|
||||
~QMetalComputePipeline();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
|
||||
QMetalComputePipelineData *d;
|
||||
uint generation = 0;
|
||||
int lastActiveFrameSlot = -1;
|
||||
friend class QRhiMetal;
|
||||
};
|
||||
|
||||
struct QMetalCommandBufferData;
|
||||
struct QMetalSwapChain;
|
||||
|
||||
struct QMetalCommandBuffer : public QRhiCommandBuffer
|
||||
{
|
||||
QMetalCommandBuffer(QRhiImplementation *rhi);
|
||||
~QMetalCommandBuffer();
|
||||
void destroy() override;
|
||||
|
||||
QMetalCommandBufferData *d = nullptr;
|
||||
QRhiMetalCommandBufferNativeHandles nativeHandlesStruct;
|
||||
|
||||
enum PassType {
|
||||
NoPass,
|
||||
RenderPass,
|
||||
ComputePass
|
||||
};
|
||||
|
||||
// per-pass (render or compute command encoder) persistent state
|
||||
PassType recordingPass;
|
||||
QRhiRenderTarget *currentTarget;
|
||||
|
||||
// per-pass (render or compute command encoder) volatile (cached) state
|
||||
QMetalGraphicsPipeline *currentGraphicsPipeline;
|
||||
QMetalComputePipeline *currentComputePipeline;
|
||||
uint currentPipelineGeneration;
|
||||
QMetalShaderResourceBindings *currentGraphicsSrb;
|
||||
QMetalShaderResourceBindings *currentComputeSrb;
|
||||
uint currentSrbGeneration;
|
||||
int currentResSlot;
|
||||
QMetalBuffer *currentIndexBuffer;
|
||||
quint32 currentIndexOffset;
|
||||
QRhiCommandBuffer::IndexFormat currentIndexFormat;
|
||||
int currentCullMode;
|
||||
int currentTriangleFillMode;
|
||||
int currentFrontFaceWinding;
|
||||
QPair<float, float> currentDepthBiasValues;
|
||||
|
||||
const QRhiNativeHandles *nativeHandles();
|
||||
void resetState(double lastGpuTime = 0);
|
||||
void resetPerPassState();
|
||||
void resetPerPassCachedState();
|
||||
};
|
||||
|
||||
struct QMetalSwapChainData;
|
||||
|
||||
struct QMetalSwapChain : public QRhiSwapChain
|
||||
{
|
||||
QMetalSwapChain(QRhiImplementation *rhi);
|
||||
~QMetalSwapChain();
|
||||
void destroy() override;
|
||||
|
||||
QRhiCommandBuffer *currentFrameCommandBuffer() override;
|
||||
QRhiRenderTarget *currentFrameRenderTarget() override;
|
||||
QSize surfacePixelSize() override;
|
||||
bool isFormatSupported(Format f) override;
|
||||
|
||||
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
|
||||
|
||||
bool createOrResize() override;
|
||||
|
||||
virtual QRhiSwapChainHdrInfo hdrInfo() override;
|
||||
|
||||
void chooseFormats();
|
||||
void waitUntilCompleted(int slot);
|
||||
|
||||
QWindow *window = nullptr;
|
||||
QSize pixelSize;
|
||||
int currentFrameSlot = 0; // 0..QMTL_FRAMES_IN_FLIGHT-1
|
||||
int frameCount = 0;
|
||||
int samples = 1;
|
||||
QMetalSwapChainRenderTarget rtWrapper;
|
||||
QMetalCommandBuffer cbWrapper;
|
||||
QMetalRenderBuffer *ds = nullptr;
|
||||
QMetalSwapChainData *d = nullptr;
|
||||
};
|
||||
|
||||
struct QRhiMetalData;
|
||||
|
||||
class QRhiMetal : public QRhiImplementation
|
||||
{
|
||||
public:
|
||||
QRhiMetal(QRhiMetalInitParams *params, QRhiMetalNativeHandles *importDevice = nullptr);
|
||||
~QRhiMetal();
|
||||
|
||||
static bool probe(QRhiMetalInitParams *params);
|
||||
static QRhiSwapChainProxyData updateSwapChainProxyData(QWindow *window);
|
||||
|
||||
bool create(QRhi::Flags flags) override;
|
||||
void destroy() override;
|
||||
|
||||
QRhiGraphicsPipeline *createGraphicsPipeline() override;
|
||||
QRhiComputePipeline *createComputePipeline() override;
|
||||
QRhiShaderResourceBindings *createShaderResourceBindings() override;
|
||||
QRhiBuffer *createBuffer(QRhiBuffer::Type type,
|
||||
QRhiBuffer::UsageFlags usage,
|
||||
quint32 size) override;
|
||||
QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount,
|
||||
QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint) override;
|
||||
QRhiTexture *createTexture(QRhiTexture::Format format,
|
||||
const QSize &pixelSize,
|
||||
int depth,
|
||||
int arraySize,
|
||||
int sampleCount,
|
||||
QRhiTexture::Flags flags) override;
|
||||
QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
|
||||
QRhiSampler::Filter minFilter,
|
||||
QRhiSampler::Filter mipmapMode,
|
||||
QRhiSampler:: AddressMode u,
|
||||
QRhiSampler::AddressMode v,
|
||||
QRhiSampler::AddressMode w) override;
|
||||
|
||||
QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
|
||||
QRhiTextureRenderTarget::Flags flags) override;
|
||||
|
||||
QRhiSwapChain *createSwapChain() override;
|
||||
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
|
||||
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
|
||||
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
|
||||
QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
|
||||
QRhi::FrameOpResult finish() override;
|
||||
|
||||
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||
|
||||
void beginPass(QRhiCommandBuffer *cb,
|
||||
QRhiRenderTarget *rt,
|
||||
const QColor &colorClearValue,
|
||||
const QRhiDepthStencilClearValue &depthStencilClearValue,
|
||||
QRhiResourceUpdateBatch *resourceUpdates,
|
||||
QRhiCommandBuffer::BeginPassFlags flags) override;
|
||||
void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||
|
||||
void setGraphicsPipeline(QRhiCommandBuffer *cb,
|
||||
QRhiGraphicsPipeline *ps) override;
|
||||
|
||||
void setShaderResources(QRhiCommandBuffer *cb,
|
||||
QRhiShaderResourceBindings *srb,
|
||||
int dynamicOffsetCount,
|
||||
const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
|
||||
|
||||
void setVertexInput(QRhiCommandBuffer *cb,
|
||||
int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
|
||||
QRhiBuffer *indexBuf, quint32 indexOffset,
|
||||
QRhiCommandBuffer::IndexFormat indexFormat) override;
|
||||
|
||||
void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
|
||||
void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
|
||||
void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
|
||||
void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
|
||||
|
||||
void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
|
||||
quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
|
||||
|
||||
void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
|
||||
quint32 instanceCount, quint32 firstIndex,
|
||||
qint32 vertexOffset, quint32 firstInstance) override;
|
||||
|
||||
void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
|
||||
void debugMarkEnd(QRhiCommandBuffer *cb) override;
|
||||
void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
|
||||
|
||||
void beginComputePass(QRhiCommandBuffer *cb,
|
||||
QRhiResourceUpdateBatch *resourceUpdates,
|
||||
QRhiCommandBuffer::BeginPassFlags flags) override;
|
||||
void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||
void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
|
||||
void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;
|
||||
|
||||
const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
|
||||
void beginExternal(QRhiCommandBuffer *cb) override;
|
||||
void endExternal(QRhiCommandBuffer *cb) override;
|
||||
double lastCompletedGpuTime(QRhiCommandBuffer *cb) override;
|
||||
|
||||
QList<int> supportedSampleCounts() const override;
|
||||
int ubufAlignment() const override;
|
||||
bool isYUpInFramebuffer() const override;
|
||||
bool isYUpInNDC() const override;
|
||||
bool isClipDepthZeroToOne() const override;
|
||||
QMatrix4x4 clipSpaceCorrMatrix() const override;
|
||||
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
|
||||
bool isFeatureSupported(QRhi::Feature feature) const override;
|
||||
int resourceLimit(QRhi::ResourceLimit limit) const override;
|
||||
const QRhiNativeHandles *nativeHandles() override;
|
||||
QRhiDriverInfo driverInfo() const override;
|
||||
QRhiStats statistics() override;
|
||||
bool makeThreadLocalNativeContextCurrent() override;
|
||||
void releaseCachedResources() override;
|
||||
bool isDeviceLost() const override;
|
||||
|
||||
QByteArray pipelineCacheData() override;
|
||||
void setPipelineCacheData(const QByteArray &data) override;
|
||||
|
||||
void executeDeferredReleases(bool forced = false);
|
||||
void finishActiveReadbacks(bool forced = false);
|
||||
qsizetype subresUploadByteSize(const QRhiTextureSubresourceUploadDescription &subresDesc) const;
|
||||
void enqueueSubresUpload(QMetalTexture *texD, void *mp, void *blitEncPtr,
|
||||
int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc,
|
||||
qsizetype *curOfs);
|
||||
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
|
||||
void executeBufferHostWritesForSlot(QMetalBuffer *bufD, int slot);
|
||||
void executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD);
|
||||
static const int SUPPORTED_STAGES = 5;
|
||||
void enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD,
|
||||
QMetalCommandBuffer *cbD,
|
||||
int dynamicOffsetCount,
|
||||
const QRhiCommandBuffer::DynamicOffset *dynamicOffsets,
|
||||
bool offsetOnlyChange,
|
||||
const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[SUPPORTED_STAGES]);
|
||||
int effectiveSampleCount(int sampleCount) const;
|
||||
struct TessDrawArgs {
|
||||
QMetalCommandBuffer *cbD;
|
||||
enum {
|
||||
NonIndexed,
|
||||
U16Indexed,
|
||||
U32Indexed
|
||||
} type;
|
||||
struct NonIndexedArgs {
|
||||
quint32 vertexCount;
|
||||
quint32 instanceCount;
|
||||
quint32 firstVertex;
|
||||
quint32 firstInstance;
|
||||
};
|
||||
struct IndexedArgs {
|
||||
quint32 indexCount;
|
||||
quint32 instanceCount;
|
||||
quint32 firstIndex;
|
||||
qint32 vertexOffset;
|
||||
quint32 firstInstance;
|
||||
void *indexBuffer;
|
||||
};
|
||||
union {
|
||||
NonIndexedArgs draw;
|
||||
IndexedArgs drawIndexed;
|
||||
};
|
||||
};
|
||||
void tessellatedDraw(const TessDrawArgs &args);
|
||||
|
||||
QRhi::Flags rhiFlags;
|
||||
bool importedDevice = false;
|
||||
bool importedCmdQueue = false;
|
||||
QMetalSwapChain *currentSwapChain = nullptr;
|
||||
QSet<QMetalSwapChain *> swapchains;
|
||||
QRhiMetalNativeHandles nativeHandlesStruct;
|
||||
QRhiDriverInfo driverInfoStruct;
|
||||
quint32 osMajor = 0;
|
||||
quint32 osMinor = 0;
|
||||
|
||||
struct {
|
||||
int maxTextureSize = 4096;
|
||||
bool baseVertexAndInstance = true;
|
||||
QVector<int> supportedSampleCounts;
|
||||
bool isAppleGPU = false;
|
||||
int maxThreadGroupSize = 512;
|
||||
} caps;
|
||||
|
||||
QRhiMetalData *d = nullptr;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2019 The Qt Company Ltd.
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include "qrhinull_p_p.h"
|
||||
#include "qrhinull_p.h"
|
||||
#include <qmath.h>
|
||||
#include <QPainter>
|
||||
|
||||
@ -9,10 +9,13 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QRhiNullInitParams
|
||||
\internal
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
\brief Null backend specific initialization parameters.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QRhi
|
||||
for details.
|
||||
|
||||
A Null QRhi needs no special parameters for initialization.
|
||||
|
||||
\badcode
|
||||
@ -28,9 +31,12 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QRhiNullNativeHandles
|
||||
\internal
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
\brief Empty.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QRhi
|
||||
for details.
|
||||
*/
|
||||
|
||||
QRhiNull::QRhiNull(QRhiNullInitParams *params)
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Copyright (C) 2019 The Qt Company Ltd.
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QRHINULL_H
|
||||
#define QRHINULL_H
|
||||
#ifndef QRHINULL_P_H
|
||||
#define QRHINULL_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
@ -15,16 +15,279 @@
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <private/qrhi_p.h>
|
||||
#include "qrhi_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
struct Q_GUI_EXPORT QRhiNullInitParams : public QRhiInitParams
|
||||
struct QNullBuffer : public QRhiBuffer
|
||||
{
|
||||
QNullBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size);
|
||||
~QNullBuffer();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
char *beginFullDynamicBufferUpdateForCurrentFrame() override;
|
||||
|
||||
char *data = nullptr;
|
||||
};
|
||||
|
||||
struct Q_GUI_EXPORT QRhiNullNativeHandles : public QRhiNativeHandles
|
||||
struct QNullRenderBuffer : public QRhiRenderBuffer
|
||||
{
|
||||
QNullRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint);
|
||||
~QNullRenderBuffer();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
QRhiTexture::Format backingFormat() const override;
|
||||
|
||||
bool valid = false;
|
||||
uint generation = 0;
|
||||
};
|
||||
|
||||
struct QNullTexture : public QRhiTexture
|
||||
{
|
||||
QNullTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
|
||||
int arraySize, int sampleCount, Flags flags);
|
||||
~QNullTexture();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
bool createFrom(NativeTexture src) override;
|
||||
|
||||
bool valid = false;
|
||||
QVarLengthArray<std::array<QImage, QRhi::MAX_MIP_LEVELS>, 6> image;
|
||||
uint generation = 0;
|
||||
};
|
||||
|
||||
struct QNullSampler : public QRhiSampler
|
||||
{
|
||||
QNullSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
|
||||
AddressMode u, AddressMode v, AddressMode w);
|
||||
~QNullSampler();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
};
|
||||
|
||||
struct QNullRenderPassDescriptor : public QRhiRenderPassDescriptor
|
||||
{
|
||||
QNullRenderPassDescriptor(QRhiImplementation *rhi);
|
||||
~QNullRenderPassDescriptor();
|
||||
void destroy() override;
|
||||
bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
|
||||
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
|
||||
QVector<quint32> serializedFormat() const override;
|
||||
};
|
||||
|
||||
struct QNullRenderTargetData
|
||||
{
|
||||
QNullRenderTargetData(QRhiImplementation *) { }
|
||||
|
||||
QNullRenderPassDescriptor *rp = nullptr;
|
||||
QSize pixelSize;
|
||||
float dpr = 1;
|
||||
QRhiRenderTargetAttachmentTracker::ResIdList currentResIdList;
|
||||
};
|
||||
|
||||
struct QNullSwapChainRenderTarget : public QRhiSwapChainRenderTarget
|
||||
{
|
||||
QNullSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain);
|
||||
~QNullSwapChainRenderTarget();
|
||||
void destroy() override;
|
||||
|
||||
QSize pixelSize() const override;
|
||||
float devicePixelRatio() const override;
|
||||
int sampleCount() const override;
|
||||
|
||||
QNullRenderTargetData d;
|
||||
};
|
||||
|
||||
struct QNullTextureRenderTarget : public QRhiTextureRenderTarget
|
||||
{
|
||||
QNullTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
|
||||
~QNullTextureRenderTarget();
|
||||
void destroy() override;
|
||||
|
||||
QSize pixelSize() const override;
|
||||
float devicePixelRatio() const override;
|
||||
int sampleCount() const override;
|
||||
|
||||
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
|
||||
bool create() override;
|
||||
|
||||
QNullRenderTargetData d;
|
||||
};
|
||||
|
||||
struct QNullShaderResourceBindings : public QRhiShaderResourceBindings
|
||||
{
|
||||
QNullShaderResourceBindings(QRhiImplementation *rhi);
|
||||
~QNullShaderResourceBindings();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
void updateResources(UpdateFlags flags) override;
|
||||
};
|
||||
|
||||
struct QNullGraphicsPipeline : public QRhiGraphicsPipeline
|
||||
{
|
||||
QNullGraphicsPipeline(QRhiImplementation *rhi);
|
||||
~QNullGraphicsPipeline();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
};
|
||||
|
||||
struct QNullComputePipeline : public QRhiComputePipeline
|
||||
{
|
||||
QNullComputePipeline(QRhiImplementation *rhi);
|
||||
~QNullComputePipeline();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
};
|
||||
|
||||
struct QNullCommandBuffer : public QRhiCommandBuffer
|
||||
{
|
||||
QNullCommandBuffer(QRhiImplementation *rhi);
|
||||
~QNullCommandBuffer();
|
||||
void destroy() override;
|
||||
};
|
||||
|
||||
struct QNullSwapChain : public QRhiSwapChain
|
||||
{
|
||||
QNullSwapChain(QRhiImplementation *rhi);
|
||||
~QNullSwapChain();
|
||||
void destroy() override;
|
||||
|
||||
QRhiCommandBuffer *currentFrameCommandBuffer() override;
|
||||
QRhiRenderTarget *currentFrameRenderTarget() override;
|
||||
|
||||
QSize surfacePixelSize() override;
|
||||
bool isFormatSupported(Format f) override;
|
||||
|
||||
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
|
||||
bool createOrResize() override;
|
||||
|
||||
QWindow *window = nullptr;
|
||||
QNullSwapChainRenderTarget rt;
|
||||
QNullCommandBuffer cb;
|
||||
int frameCount = 0;
|
||||
};
|
||||
|
||||
class QRhiNull : public QRhiImplementation
|
||||
{
|
||||
public:
|
||||
QRhiNull(QRhiNullInitParams *params);
|
||||
|
||||
bool create(QRhi::Flags flags) override;
|
||||
void destroy() override;
|
||||
|
||||
QRhiGraphicsPipeline *createGraphicsPipeline() override;
|
||||
QRhiComputePipeline *createComputePipeline() override;
|
||||
QRhiShaderResourceBindings *createShaderResourceBindings() override;
|
||||
QRhiBuffer *createBuffer(QRhiBuffer::Type type,
|
||||
QRhiBuffer::UsageFlags usage,
|
||||
quint32 size) override;
|
||||
QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount,
|
||||
QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint) override;
|
||||
QRhiTexture *createTexture(QRhiTexture::Format format,
|
||||
const QSize &pixelSize,
|
||||
int depth,
|
||||
int arraySize,
|
||||
int sampleCount,
|
||||
QRhiTexture::Flags flags) override;
|
||||
QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
|
||||
QRhiSampler::Filter minFilter,
|
||||
QRhiSampler::Filter mipmapMode,
|
||||
QRhiSampler:: AddressMode u,
|
||||
QRhiSampler::AddressMode v,
|
||||
QRhiSampler::AddressMode w) override;
|
||||
|
||||
QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
|
||||
QRhiTextureRenderTarget::Flags flags) override;
|
||||
|
||||
QRhiSwapChain *createSwapChain() override;
|
||||
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
|
||||
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
|
||||
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
|
||||
QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
|
||||
QRhi::FrameOpResult finish() override;
|
||||
|
||||
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||
|
||||
void beginPass(QRhiCommandBuffer *cb,
|
||||
QRhiRenderTarget *rt,
|
||||
const QColor &colorClearValue,
|
||||
const QRhiDepthStencilClearValue &depthStencilClearValue,
|
||||
QRhiResourceUpdateBatch *resourceUpdates,
|
||||
QRhiCommandBuffer::BeginPassFlags flags) override;
|
||||
void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||
|
||||
void setGraphicsPipeline(QRhiCommandBuffer *cb,
|
||||
QRhiGraphicsPipeline *ps) override;
|
||||
|
||||
void setShaderResources(QRhiCommandBuffer *cb,
|
||||
QRhiShaderResourceBindings *srb,
|
||||
int dynamicOffsetCount,
|
||||
const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
|
||||
|
||||
void setVertexInput(QRhiCommandBuffer *cb,
|
||||
int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
|
||||
QRhiBuffer *indexBuf, quint32 indexOffset,
|
||||
QRhiCommandBuffer::IndexFormat indexFormat) override;
|
||||
|
||||
void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
|
||||
void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
|
||||
void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
|
||||
void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
|
||||
|
||||
void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
|
||||
quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
|
||||
|
||||
void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
|
||||
quint32 instanceCount, quint32 firstIndex,
|
||||
qint32 vertexOffset, quint32 firstInstance) override;
|
||||
|
||||
void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
|
||||
void debugMarkEnd(QRhiCommandBuffer *cb) override;
|
||||
void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
|
||||
|
||||
void beginComputePass(QRhiCommandBuffer *cb,
|
||||
QRhiResourceUpdateBatch *resourceUpdates,
|
||||
QRhiCommandBuffer::BeginPassFlags flags) override;
|
||||
void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||
void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
|
||||
void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;
|
||||
|
||||
const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
|
||||
void beginExternal(QRhiCommandBuffer *cb) override;
|
||||
void endExternal(QRhiCommandBuffer *cb) override;
|
||||
double lastCompletedGpuTime(QRhiCommandBuffer *cb) override;
|
||||
|
||||
QList<int> supportedSampleCounts() const override;
|
||||
int ubufAlignment() const override;
|
||||
bool isYUpInFramebuffer() const override;
|
||||
bool isYUpInNDC() const override;
|
||||
bool isClipDepthZeroToOne() const override;
|
||||
QMatrix4x4 clipSpaceCorrMatrix() const override;
|
||||
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
|
||||
bool isFeatureSupported(QRhi::Feature feature) const override;
|
||||
int resourceLimit(QRhi::ResourceLimit limit) const override;
|
||||
const QRhiNativeHandles *nativeHandles() override;
|
||||
QRhiDriverInfo driverInfo() const override;
|
||||
QRhiStats statistics() override;
|
||||
bool makeThreadLocalNativeContextCurrent() override;
|
||||
void releaseCachedResources() override;
|
||||
bool isDeviceLost() const override;
|
||||
|
||||
QByteArray pipelineCacheData() override;
|
||||
void setPipelineCacheData(const QByteArray &data) override;
|
||||
|
||||
void simulateTextureUpload(const QRhiResourceUpdateBatchPrivate::TextureOp &u);
|
||||
void simulateTextureCopy(const QRhiResourceUpdateBatchPrivate::TextureOp &u);
|
||||
void simulateTextureGenMips(const QRhiResourceUpdateBatchPrivate::TextureOp &u);
|
||||
|
||||
QRhiNullNativeHandles nativeHandlesStruct;
|
||||
QRhiSwapChain *currentSwapChain = nullptr;
|
||||
QNullCommandBuffer offscreenCommandBuffer;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -1,296 +0,0 @@
|
||||
// Copyright (C) 2019 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QRHINULL_P_H
|
||||
#define QRHINULL_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "qrhinull_p.h"
|
||||
#include "qrhi_p_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
struct QNullBuffer : public QRhiBuffer
|
||||
{
|
||||
QNullBuffer(QRhiImplementation *rhi, Type type, UsageFlags usage, quint32 size);
|
||||
~QNullBuffer();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
char *beginFullDynamicBufferUpdateForCurrentFrame() override;
|
||||
|
||||
char *data = nullptr;
|
||||
};
|
||||
|
||||
struct QNullRenderBuffer : public QRhiRenderBuffer
|
||||
{
|
||||
QNullRenderBuffer(QRhiImplementation *rhi, Type type, const QSize &pixelSize,
|
||||
int sampleCount, QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint);
|
||||
~QNullRenderBuffer();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
QRhiTexture::Format backingFormat() const override;
|
||||
|
||||
bool valid = false;
|
||||
uint generation = 0;
|
||||
};
|
||||
|
||||
struct QNullTexture : public QRhiTexture
|
||||
{
|
||||
QNullTexture(QRhiImplementation *rhi, Format format, const QSize &pixelSize, int depth,
|
||||
int arraySize, int sampleCount, Flags flags);
|
||||
~QNullTexture();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
bool createFrom(NativeTexture src) override;
|
||||
|
||||
bool valid = false;
|
||||
QVarLengthArray<std::array<QImage, QRhi::MAX_MIP_LEVELS>, 6> image;
|
||||
uint generation = 0;
|
||||
};
|
||||
|
||||
struct QNullSampler : public QRhiSampler
|
||||
{
|
||||
QNullSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
|
||||
AddressMode u, AddressMode v, AddressMode w);
|
||||
~QNullSampler();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
};
|
||||
|
||||
struct QNullRenderPassDescriptor : public QRhiRenderPassDescriptor
|
||||
{
|
||||
QNullRenderPassDescriptor(QRhiImplementation *rhi);
|
||||
~QNullRenderPassDescriptor();
|
||||
void destroy() override;
|
||||
bool isCompatible(const QRhiRenderPassDescriptor *other) const override;
|
||||
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() const override;
|
||||
QVector<quint32> serializedFormat() const override;
|
||||
};
|
||||
|
||||
struct QNullRenderTargetData
|
||||
{
|
||||
QNullRenderTargetData(QRhiImplementation *) { }
|
||||
|
||||
QNullRenderPassDescriptor *rp = nullptr;
|
||||
QSize pixelSize;
|
||||
float dpr = 1;
|
||||
QRhiRenderTargetAttachmentTracker::ResIdList currentResIdList;
|
||||
};
|
||||
|
||||
struct QNullSwapChainRenderTarget : public QRhiSwapChainRenderTarget
|
||||
{
|
||||
QNullSwapChainRenderTarget(QRhiImplementation *rhi, QRhiSwapChain *swapchain);
|
||||
~QNullSwapChainRenderTarget();
|
||||
void destroy() override;
|
||||
|
||||
QSize pixelSize() const override;
|
||||
float devicePixelRatio() const override;
|
||||
int sampleCount() const override;
|
||||
|
||||
QNullRenderTargetData d;
|
||||
};
|
||||
|
||||
struct QNullTextureRenderTarget : public QRhiTextureRenderTarget
|
||||
{
|
||||
QNullTextureRenderTarget(QRhiImplementation *rhi, const QRhiTextureRenderTargetDescription &desc, Flags flags);
|
||||
~QNullTextureRenderTarget();
|
||||
void destroy() override;
|
||||
|
||||
QSize pixelSize() const override;
|
||||
float devicePixelRatio() const override;
|
||||
int sampleCount() const override;
|
||||
|
||||
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
|
||||
bool create() override;
|
||||
|
||||
QNullRenderTargetData d;
|
||||
};
|
||||
|
||||
struct QNullShaderResourceBindings : public QRhiShaderResourceBindings
|
||||
{
|
||||
QNullShaderResourceBindings(QRhiImplementation *rhi);
|
||||
~QNullShaderResourceBindings();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
void updateResources(UpdateFlags flags) override;
|
||||
};
|
||||
|
||||
struct QNullGraphicsPipeline : public QRhiGraphicsPipeline
|
||||
{
|
||||
QNullGraphicsPipeline(QRhiImplementation *rhi);
|
||||
~QNullGraphicsPipeline();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
};
|
||||
|
||||
struct QNullComputePipeline : public QRhiComputePipeline
|
||||
{
|
||||
QNullComputePipeline(QRhiImplementation *rhi);
|
||||
~QNullComputePipeline();
|
||||
void destroy() override;
|
||||
bool create() override;
|
||||
};
|
||||
|
||||
struct QNullCommandBuffer : public QRhiCommandBuffer
|
||||
{
|
||||
QNullCommandBuffer(QRhiImplementation *rhi);
|
||||
~QNullCommandBuffer();
|
||||
void destroy() override;
|
||||
};
|
||||
|
||||
struct QNullSwapChain : public QRhiSwapChain
|
||||
{
|
||||
QNullSwapChain(QRhiImplementation *rhi);
|
||||
~QNullSwapChain();
|
||||
void destroy() override;
|
||||
|
||||
QRhiCommandBuffer *currentFrameCommandBuffer() override;
|
||||
QRhiRenderTarget *currentFrameRenderTarget() override;
|
||||
|
||||
QSize surfacePixelSize() override;
|
||||
bool isFormatSupported(Format f) override;
|
||||
|
||||
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
|
||||
bool createOrResize() override;
|
||||
|
||||
QWindow *window = nullptr;
|
||||
QNullSwapChainRenderTarget rt;
|
||||
QNullCommandBuffer cb;
|
||||
int frameCount = 0;
|
||||
};
|
||||
|
||||
class QRhiNull : public QRhiImplementation
|
||||
{
|
||||
public:
|
||||
QRhiNull(QRhiNullInitParams *params);
|
||||
|
||||
bool create(QRhi::Flags flags) override;
|
||||
void destroy() override;
|
||||
|
||||
QRhiGraphicsPipeline *createGraphicsPipeline() override;
|
||||
QRhiComputePipeline *createComputePipeline() override;
|
||||
QRhiShaderResourceBindings *createShaderResourceBindings() override;
|
||||
QRhiBuffer *createBuffer(QRhiBuffer::Type type,
|
||||
QRhiBuffer::UsageFlags usage,
|
||||
quint32 size) override;
|
||||
QRhiRenderBuffer *createRenderBuffer(QRhiRenderBuffer::Type type,
|
||||
const QSize &pixelSize,
|
||||
int sampleCount,
|
||||
QRhiRenderBuffer::Flags flags,
|
||||
QRhiTexture::Format backingFormatHint) override;
|
||||
QRhiTexture *createTexture(QRhiTexture::Format format,
|
||||
const QSize &pixelSize,
|
||||
int depth,
|
||||
int arraySize,
|
||||
int sampleCount,
|
||||
QRhiTexture::Flags flags) override;
|
||||
QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
|
||||
QRhiSampler::Filter minFilter,
|
||||
QRhiSampler::Filter mipmapMode,
|
||||
QRhiSampler:: AddressMode u,
|
||||
QRhiSampler::AddressMode v,
|
||||
QRhiSampler::AddressMode w) override;
|
||||
|
||||
QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
|
||||
QRhiTextureRenderTarget::Flags flags) override;
|
||||
|
||||
QRhiSwapChain *createSwapChain() override;
|
||||
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
|
||||
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
|
||||
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
|
||||
QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
|
||||
QRhi::FrameOpResult finish() override;
|
||||
|
||||
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||
|
||||
void beginPass(QRhiCommandBuffer *cb,
|
||||
QRhiRenderTarget *rt,
|
||||
const QColor &colorClearValue,
|
||||
const QRhiDepthStencilClearValue &depthStencilClearValue,
|
||||
QRhiResourceUpdateBatch *resourceUpdates,
|
||||
QRhiCommandBuffer::BeginPassFlags flags) override;
|
||||
void endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||
|
||||
void setGraphicsPipeline(QRhiCommandBuffer *cb,
|
||||
QRhiGraphicsPipeline *ps) override;
|
||||
|
||||
void setShaderResources(QRhiCommandBuffer *cb,
|
||||
QRhiShaderResourceBindings *srb,
|
||||
int dynamicOffsetCount,
|
||||
const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) override;
|
||||
|
||||
void setVertexInput(QRhiCommandBuffer *cb,
|
||||
int startBinding, int bindingCount, const QRhiCommandBuffer::VertexInput *bindings,
|
||||
QRhiBuffer *indexBuf, quint32 indexOffset,
|
||||
QRhiCommandBuffer::IndexFormat indexFormat) override;
|
||||
|
||||
void setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport) override;
|
||||
void setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor) override;
|
||||
void setBlendConstants(QRhiCommandBuffer *cb, const QColor &c) override;
|
||||
void setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) override;
|
||||
|
||||
void draw(QRhiCommandBuffer *cb, quint32 vertexCount,
|
||||
quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) override;
|
||||
|
||||
void drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
|
||||
quint32 instanceCount, quint32 firstIndex,
|
||||
qint32 vertexOffset, quint32 firstInstance) override;
|
||||
|
||||
void debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name) override;
|
||||
void debugMarkEnd(QRhiCommandBuffer *cb) override;
|
||||
void debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg) override;
|
||||
|
||||
void beginComputePass(QRhiCommandBuffer *cb,
|
||||
QRhiResourceUpdateBatch *resourceUpdates,
|
||||
QRhiCommandBuffer::BeginPassFlags flags) override;
|
||||
void endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||
void setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *ps) override;
|
||||
void dispatch(QRhiCommandBuffer *cb, int x, int y, int z) override;
|
||||
|
||||
const QRhiNativeHandles *nativeHandles(QRhiCommandBuffer *cb) override;
|
||||
void beginExternal(QRhiCommandBuffer *cb) override;
|
||||
void endExternal(QRhiCommandBuffer *cb) override;
|
||||
double lastCompletedGpuTime(QRhiCommandBuffer *cb) override;
|
||||
|
||||
QList<int> supportedSampleCounts() const override;
|
||||
int ubufAlignment() const override;
|
||||
bool isYUpInFramebuffer() const override;
|
||||
bool isYUpInNDC() const override;
|
||||
bool isClipDepthZeroToOne() const override;
|
||||
QMatrix4x4 clipSpaceCorrMatrix() const override;
|
||||
bool isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture::Flags flags) const override;
|
||||
bool isFeatureSupported(QRhi::Feature feature) const override;
|
||||
int resourceLimit(QRhi::ResourceLimit limit) const override;
|
||||
const QRhiNativeHandles *nativeHandles() override;
|
||||
QRhiDriverInfo driverInfo() const override;
|
||||
QRhiStats statistics() override;
|
||||
bool makeThreadLocalNativeContextCurrent() override;
|
||||
void releaseCachedResources() override;
|
||||
bool isDeviceLost() const override;
|
||||
|
||||
QByteArray pipelineCacheData() override;
|
||||
void setPipelineCacheData(const QByteArray &data) override;
|
||||
|
||||
void simulateTextureUpload(const QRhiResourceUpdateBatchPrivate::TextureOp &u);
|
||||
void simulateTextureCopy(const QRhiResourceUpdateBatchPrivate::TextureOp &u);
|
||||
void simulateTextureGenMips(const QRhiResourceUpdateBatchPrivate::TextureOp &u);
|
||||
|
||||
QRhiNullNativeHandles nativeHandlesStruct;
|
||||
QRhiSwapChain *currentSwapChain = nullptr;
|
||||
QNullCommandBuffer offscreenCommandBuffer;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2019 The Qt Company Ltd.
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include "qrhivulkan_p_p.h"
|
||||
#include "qrhivulkan_p.h"
|
||||
#include "qrhivulkanext_p.h"
|
||||
#include <qpa/qplatformvulkaninstance.h>
|
||||
|
||||
@ -60,10 +60,13 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QRhiVulkanInitParams
|
||||
\internal
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
\brief Vulkan specific initialization parameters.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QRhi
|
||||
for details.
|
||||
|
||||
A Vulkan-based QRhi needs at minimum a valid QVulkanInstance. It is up to
|
||||
the user to ensure this is available and initialized. This is typically
|
||||
done in main() similarly to the following:
|
||||
@ -165,19 +168,81 @@ QT_BEGIN_NAMESPACE
|
||||
available.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiVulkanInitParams::inst
|
||||
|
||||
The QVulkanInstance that has already been successfully
|
||||
\l{QVulkanInstance::create()}{created}, required.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiVulkanInitParams::window
|
||||
|
||||
Optional, but recommended when targeting a QWindow.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiVulkanInitParams::deviceExtensions
|
||||
|
||||
Optional, empty by default. The list of Vulkan device extensions to enable.
|
||||
Unsupported extensions are ignored gracefully.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QRhiVulkanNativeHandles
|
||||
\internal
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
\brief Collects device, queue, and other Vulkan objects that are used by the QRhi.
|
||||
|
||||
\note Ownership of the Vulkan objects is never transferred.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QRhi
|
||||
for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiVulkanNativeHandles::physDev
|
||||
|
||||
When different from \nullptr, specifies the Vulkan physical device to use.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiVulkanNativeHandles::dev
|
||||
|
||||
When wanting to import not just a physical device, but also use an already
|
||||
existing VkDevice, set this and the graphics queue index and family index.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiVulkanNativeHandles::gfxQueueFamilyIdx
|
||||
|
||||
Graphics queue family index.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiVulkanNativeHandles::gfxQueueIdx
|
||||
|
||||
Graphics queue index.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiVulkanNativeHandles::gfxQueue
|
||||
|
||||
Output only, not used by QRhi::create(), only set by the
|
||||
QRhi::nativeHandles() accessor. The graphics VkQueue used by the QRhi.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiVulkanNativeHandles::vmemAllocator
|
||||
|
||||
Relevant only when importing an existing memory allocator object,
|
||||
leave it set to \nullptr otherwise.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QRhiVulkanCommandBufferNativeHandles
|
||||
\internal
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
\brief Holds the Vulkan command buffer object that is backing a QRhiCommandBuffer.
|
||||
|
||||
\note The Vulkan command buffer object is only guaranteed to be valid, and
|
||||
@ -185,15 +250,33 @@ QT_BEGIN_NAMESPACE
|
||||
\l{QRhi::beginFrame()}{beginFrame()} - \l{QRhi::endFrame()}{endFrame()} or
|
||||
\l{QRhi::beginOffscreenFrame()}{beginOffscreenFrame()} -
|
||||
\l{QRhi::endOffscreenFrame()}{endOffscreenFrame()} pair.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QRhi
|
||||
for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiVulkanCommandBufferNativeHandles::commandBuffer
|
||||
|
||||
The VkCommandBuffer object.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QRhiVulkanRenderPassNativeHandles
|
||||
\internal
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
\brief Holds the Vulkan render pass object backing a QRhiRenderPassDescriptor.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QRhi
|
||||
for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiVulkanRenderPassNativeHandles::renderPass
|
||||
|
||||
The VkRenderPass object.
|
||||
*/
|
||||
|
||||
template <class Int>
|
||||
inline Int aligned(Int v, Int byteAlign)
|
||||
{
|
||||
@ -222,6 +305,13 @@ static inline VmaAllocator toVmaAllocator(QVkAllocator a)
|
||||
return reinterpret_cast<VmaAllocator>(a);
|
||||
}
|
||||
|
||||
/*!
|
||||
\return the list of instance extensions that are expected to be enabled on
|
||||
the QVulkanInstance that is used for the Vulkan-based QRhi.
|
||||
|
||||
The returned list can be safely passed to QVulkanInstance::setExtensions()
|
||||
as-is, because unsupported extensions are filtered out automatically.
|
||||
*/
|
||||
QByteArrayList QRhiVulkanInitParams::preferredInstanceExtensions()
|
||||
{
|
||||
return {
|
||||
@ -229,6 +319,11 @@ QByteArrayList QRhiVulkanInitParams::preferredInstanceExtensions()
|
||||
};
|
||||
}
|
||||
|
||||
/*!
|
||||
\return the list of device extensions that are expected to be enabled on the
|
||||
\c VkDevice when creating a Vulkan-based QRhi with an externally created
|
||||
\c VkDevice object.
|
||||
*/
|
||||
QByteArrayList QRhiVulkanInitParams::preferredExtensionsForImportedDevice()
|
||||
{
|
||||
return {
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2019 The Qt Company Ltd.
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include "qshader_p_p.h"
|
||||
#include "qshader_p.h"
|
||||
#include <QDataStream>
|
||||
#include <QBuffer>
|
||||
|
||||
@ -9,8 +9,9 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QShader
|
||||
\internal
|
||||
\ingroup painting-3D
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
|
||||
\brief Contains multiple versions of a shader translated to multiple shading languages,
|
||||
together with reflection metadata.
|
||||
@ -21,6 +22,16 @@ QT_BEGIN_NAMESPACE
|
||||
as, Vulkan, Metal, Direct3D, and OpenGL, take QShader as their input
|
||||
whenever a shader needs to be specified.
|
||||
|
||||
\warning The QRhi family of classes in the Qt Gui module, including QShader
|
||||
and QShaderDescription, offer limited compatibility guarantees. There are
|
||||
no source or binary compatibility guarantees for these classes, meaning the
|
||||
API is only guaranteed to work with the Qt version the application was
|
||||
developed against. Source incompatible changes are however aimed to be kept
|
||||
at a minimum and will only be made in minor releases (6.7, 6.8, and so on).
|
||||
To use these classes in an application, link to
|
||||
\c{Qt::GuiPrivate} (if using CMake), and include the headers with the \c
|
||||
rhi prefix, for example \c{#include <rhi/qshader.h>}.
|
||||
|
||||
A QShader instance is empty and thus invalid by default. To get a useful
|
||||
instance, the two typical methods are:
|
||||
|
||||
@ -68,8 +79,9 @@ QT_BEGIN_NAMESPACE
|
||||
can be returned or passed by value. Detach happens implicitly when calling
|
||||
a setter.
|
||||
|
||||
For reference, QRhi expects that a QShader suitable for all its
|
||||
backends contains at least the following:
|
||||
For reference, a typical, portable QRhi expects that a QShader suitable for
|
||||
all its backends contains at least the following. (this excludes support
|
||||
for core profile OpenGL contexts, add GLSL 150 or newer for that)
|
||||
|
||||
\list
|
||||
|
||||
@ -77,11 +89,11 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
\li GLSL/ES 100 source code suitable for OpenGL ES 2.0 or newer
|
||||
|
||||
\li GLSL 120 source code suitable for OpenGL 2.1
|
||||
\li GLSL 120 source code suitable for OpenGL 2.1 or newer
|
||||
|
||||
\li HLSL Shader Model 5.0 source code or the corresponding DXBC bytecode suitable for Direct3D 11
|
||||
\li HLSL Shader Model 5.0 source code or the corresponding DXBC bytecode suitable for Direct3D 11/12
|
||||
|
||||
\li Metal Shading Language 1.2 source code or the corresponding bytecode suitable for Metal
|
||||
\li Metal Shading Language 1.2 source code or the corresponding bytecode suitable for Metal 1.2 or newer
|
||||
|
||||
\endlist
|
||||
|
||||
@ -102,8 +114,8 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QShaderVersion
|
||||
\internal
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
|
||||
\brief Specifies the shading language version.
|
||||
|
||||
@ -128,6 +140,9 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
A default constructed QShaderVersion contains a version of 100 and no
|
||||
flags set.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QShader
|
||||
for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -140,13 +155,16 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QShaderKey
|
||||
\internal
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
|
||||
\brief Specifies the shading language, the version with flags, and the variant.
|
||||
|
||||
A default constructed QShaderKey has source set to SpirvShader and
|
||||
sourceVersion set to 100. sourceVariant defaults to StandardShader.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QShader
|
||||
for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -197,13 +215,16 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QShaderCode
|
||||
\internal
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
|
||||
\brief Contains source or binary code for a shader and additional metadata.
|
||||
|
||||
When shader() is empty after retrieving a QShaderCode instance from
|
||||
QShader, it indicates no shader code was found for the requested key.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QShader
|
||||
for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -226,7 +247,7 @@ void QShader::detach()
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Constructs a copy of \a other.
|
||||
*/
|
||||
QShader::QShader(const QShader &other)
|
||||
: d(other.d)
|
||||
@ -236,7 +257,7 @@ QShader::QShader(const QShader &other)
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Assigns \a other to this object.
|
||||
*/
|
||||
QShader &QShader::operator=(const QShader &other)
|
||||
{
|
||||
@ -577,16 +598,79 @@ QShader QShader::fromSerialized(const QByteArray &data)
|
||||
return bs;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QShaderVersion::QShaderVersion() = default
|
||||
*/
|
||||
|
||||
/*!
|
||||
Constructs a new QShaderVersion with version \a v and flags \a f.
|
||||
*/
|
||||
QShaderVersion::QShaderVersion(int v, Flags f)
|
||||
: m_version(v), m_flags(f)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn int QShaderVersion::version() const
|
||||
\return the version.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QShaderVersion::setVersion(int v)
|
||||
Sets the shading language version to \a v.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QShaderVersion::Flags QShaderVersion::flags() const
|
||||
\return the flags.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QShaderVersion::setFlags(Flags f)
|
||||
Sets the flags \a f.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QShaderCode::QShaderCode() = default
|
||||
*/
|
||||
|
||||
/*!
|
||||
Constructs a new QShaderCode with the specified shader source \a code and
|
||||
\a entry point name.
|
||||
*/
|
||||
QShaderCode::QShaderCode(const QByteArray &code, const QByteArray &entry)
|
||||
: m_shader(code), m_entryPoint(entry)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QByteArray QShaderCode::shader() const
|
||||
\return the shader source or bytecode.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QShaderCode::setShader(const QByteArray &code)
|
||||
Sets the shader source or byte \a code.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QByteArray QShaderCode::entryPoint() const
|
||||
\return the entry point name.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QShaderCode::setEntryPoint(const QByteArray &entry)
|
||||
Sets the \a entry point name.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QShaderKey::QShaderKey() = default
|
||||
*/
|
||||
|
||||
/*!
|
||||
Constructs a new QShaderKey with shader type \a s, version \a sver, and
|
||||
variant \a svar.
|
||||
*/
|
||||
QShaderKey::QShaderKey(QShader::Source s,
|
||||
const QShaderVersion &sver,
|
||||
QShader::Variant svar)
|
||||
@ -596,6 +680,36 @@ QShaderKey::QShaderKey(QShader::Source s,
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QShader::Source QShaderKey::source() const
|
||||
\return the shader type.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QShaderKey::setSource(QShader::Source s)
|
||||
Sets the shader type \a s.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QShaderVersion QShaderKey::sourceVersion() const
|
||||
\return the shading language version.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QShaderKey::setSourceVersion(const QShaderVersion &sver)
|
||||
Sets the shading language version \a sver.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QShader::Variant QShaderKey::sourceVariant() const
|
||||
\return the type of the variant to use.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void QShaderKey::setSourceVariant(QShader::Variant svar)
|
||||
Sets the type of variant to use to \a svar.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Returns \c true if the two QShader objects \a lhs and \a rhs are equal,
|
||||
meaning they are for the same stage with matching sets of shader source or
|
||||
@ -614,10 +728,9 @@ bool operator==(const QShader &lhs, const QShader &rhs) noexcept
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
\fn bool operator!=(const QShader &lhs, const QShader &rhs)
|
||||
|
||||
Returns \c false if the values in the two QShader objects \a a and \a b
|
||||
Returns \c false if the values in the two QShader objects \a lhs and \a rhs
|
||||
are equal; otherwise returns \c true.
|
||||
|
||||
\relates QShader
|
||||
@ -660,6 +773,8 @@ size_t qHash(const QShaderVersion &s, size_t seed) noexcept
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\return true if \a lhs is smaller than \a rhs.
|
||||
|
||||
Establishes a sorting order between the two QShaderVersion \a lhs and \a rhs.
|
||||
|
||||
\relates QShaderVersion
|
||||
@ -676,11 +791,10 @@ bool operator<(const QShaderVersion &lhs, const QShaderVersion &rhs) noexcept
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
\fn bool operator!=(const QShaderVersion &lhs, const QShaderVersion &rhs)
|
||||
|
||||
Returns \c false if the values in the two QShaderVersion objects \a a
|
||||
and \a b are equal; otherwise returns \c true.
|
||||
Returns \c false if the values in the two QShaderVersion objects \a lhs
|
||||
and \a rhs are equal; otherwise returns \c true.
|
||||
|
||||
\relates QShaderVersion
|
||||
*/
|
||||
@ -697,6 +811,8 @@ bool operator==(const QShaderKey &lhs, const QShaderKey &rhs) noexcept
|
||||
}
|
||||
|
||||
/*!
|
||||
\return true if \a lhs is smaller than \a rhs.
|
||||
|
||||
Establishes a sorting order between the two keys \a lhs and \a rhs.
|
||||
|
||||
\relates QShaderKey
|
||||
@ -719,11 +835,10 @@ bool operator<(const QShaderKey &lhs, const QShaderKey &rhs) noexcept
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
\fn bool operator!=(const QShaderKey &lhs, const QShaderKey &rhs)
|
||||
|
||||
Returns \c false if the values in the two QShaderKey objects \a a
|
||||
and \a b are equal; otherwise returns \c true.
|
||||
Returns \c false if the values in the two QShaderKey objects \a lhs
|
||||
and \a rhs are equal; otherwise returns \c true.
|
||||
|
||||
\relates QShaderKey
|
||||
*/
|
||||
@ -753,11 +868,10 @@ bool operator==(const QShaderCode &lhs, const QShaderCode &rhs) noexcept
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
\fn bool operator!=(const QShaderCode &lhs, const QShaderCode &rhs)
|
||||
|
||||
Returns \c false if the values in the two QShaderCode objects \a a
|
||||
and \a b are equal; otherwise returns \c true.
|
||||
Returns \c false if the values in the two QShaderCode objects \a lhs
|
||||
and \a rhs are equal; otherwise returns \c true.
|
||||
|
||||
\relates QShaderCode
|
||||
*/
|
||||
@ -895,6 +1009,7 @@ void QShader::removeResourceBindingMap(const QShaderKey &key)
|
||||
|
||||
/*!
|
||||
\struct QShader::SeparateToCombinedImageSamplerMapping
|
||||
\brief Mapping metadata for sampler uniforms.
|
||||
|
||||
Describes a mapping from a traditional combined image sampler uniform to
|
||||
binding points for a separate texture and sampler.
|
||||
@ -904,8 +1019,23 @@ void QShader::removeResourceBindingMap(const QShaderKey &key)
|
||||
contains a \c sampler2D (or sampler3D, etc.) uniform with the name of
|
||||
\c{_54} which corresponds to two separate resource bindings (\c 1 and \c 2)
|
||||
in the original shader.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QShader
|
||||
for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShader::SeparateToCombinedImageSamplerMapping::combinedSamplerName
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShader::SeparateToCombinedImageSamplerMapping::textureBinding
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShader::SeparateToCombinedImageSamplerMapping::samplerBinding
|
||||
*/
|
||||
|
||||
/*!
|
||||
\return the combined image sampler mapping list for \a key, or an empty
|
||||
list if there is no data available for \a key, for example because such a
|
||||
@ -953,6 +1083,7 @@ void QShader::removeSeparateToCombinedImageSamplerMappingList(const QShaderKey &
|
||||
|
||||
/*!
|
||||
\struct QShader::NativeShaderInfo
|
||||
\brief Additional metadata about the native shader code.
|
||||
|
||||
Describes information about the native shader code, if applicable. This
|
||||
becomes relevant with certain shader languages for certain shader stages,
|
||||
@ -969,8 +1100,19 @@ void QShader::removeSeparateToCombinedImageSamplerMappingList(const QShaderKey &
|
||||
not be present at all if per-patch output variables were not used. The fact
|
||||
that the shader code relies on such a buffer present can be indicated by
|
||||
the data in this struct.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QShader
|
||||
for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShader::NativeShaderInfo::flags
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShader::NativeShaderInfo::extraBufferBindings
|
||||
*/
|
||||
|
||||
/*!
|
||||
\return the native shader info struct for \a key, or an empty object if
|
||||
there is no data available for \a key, for example because such a mapping
|
||||
|
237
src/gui/rhi/qshader.h
Normal file
237
src/gui/rhi/qshader.h
Normal file
@ -0,0 +1,237 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QSHADER_H
|
||||
#define QSHADER_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is part of the RHI API, with limited compatibility guarantees.
|
||||
// Usage of this API may make your code source and binary incompatible with
|
||||
// future versions of Qt.
|
||||
//
|
||||
|
||||
#include <QtGui/qtguiglobal.h>
|
||||
#include <QtCore/qhash.h>
|
||||
#include <QtCore/qmap.h>
|
||||
#include <rhi/qshaderdescription.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
struct QShaderPrivate;
|
||||
class QShaderKey;
|
||||
|
||||
#ifdef Q_OS_INTEGRITY
|
||||
class QShaderVersion;
|
||||
size_t qHash(const QShaderVersion &, size_t = 0) noexcept;
|
||||
#endif
|
||||
|
||||
class Q_GUI_EXPORT QShaderVersion
|
||||
{
|
||||
public:
|
||||
enum Flag {
|
||||
GlslEs = 0x01
|
||||
};
|
||||
Q_DECLARE_FLAGS(Flags, Flag)
|
||||
|
||||
QShaderVersion() = default;
|
||||
QShaderVersion(int v, Flags f = Flags());
|
||||
|
||||
int version() const { return m_version; }
|
||||
void setVersion(int v) { m_version = v; }
|
||||
|
||||
Flags flags() const { return m_flags; }
|
||||
void setFlags(Flags f) { m_flags = f; }
|
||||
|
||||
private:
|
||||
int m_version = 100;
|
||||
Flags m_flags;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QShaderVersion::Flags)
|
||||
Q_DECLARE_TYPEINFO(QShaderVersion, Q_RELOCATABLE_TYPE);
|
||||
|
||||
class QShaderCode;
|
||||
Q_GUI_EXPORT size_t qHash(const QShaderCode &, size_t = 0) noexcept;
|
||||
|
||||
class Q_GUI_EXPORT QShaderCode
|
||||
{
|
||||
public:
|
||||
QShaderCode() = default;
|
||||
QShaderCode(const QByteArray &code, const QByteArray &entry = QByteArray());
|
||||
|
||||
QByteArray shader() const { return m_shader; }
|
||||
void setShader(const QByteArray &code) { m_shader = code; }
|
||||
|
||||
QByteArray entryPoint() const { return m_entryPoint; }
|
||||
void setEntryPoint(const QByteArray &entry) { m_entryPoint = entry; }
|
||||
|
||||
private:
|
||||
friend Q_GUI_EXPORT size_t qHash(const QShaderCode &, size_t) noexcept;
|
||||
|
||||
QByteArray m_shader;
|
||||
QByteArray m_entryPoint;
|
||||
};
|
||||
|
||||
Q_DECLARE_TYPEINFO(QShaderCode, Q_RELOCATABLE_TYPE);
|
||||
|
||||
class Q_GUI_EXPORT QShader
|
||||
{
|
||||
public:
|
||||
enum Stage {
|
||||
VertexStage = 0,
|
||||
TessellationControlStage,
|
||||
TessellationEvaluationStage,
|
||||
GeometryStage,
|
||||
FragmentStage,
|
||||
ComputeStage
|
||||
};
|
||||
|
||||
enum Source {
|
||||
SpirvShader = 0,
|
||||
GlslShader,
|
||||
HlslShader,
|
||||
DxbcShader, // fxc
|
||||
MslShader,
|
||||
DxilShader, // dxc
|
||||
MetalLibShader, // xcrun metal + xcrun metallib
|
||||
WgslShader
|
||||
};
|
||||
|
||||
enum Variant {
|
||||
StandardShader = 0,
|
||||
BatchableVertexShader,
|
||||
UInt16IndexedVertexAsComputeShader,
|
||||
UInt32IndexedVertexAsComputeShader,
|
||||
NonIndexedVertexAsComputeShader
|
||||
};
|
||||
|
||||
enum class SerializedFormatVersion {
|
||||
Latest = 0,
|
||||
Qt_6_5,
|
||||
Qt_6_4
|
||||
};
|
||||
|
||||
QShader();
|
||||
QShader(const QShader &other);
|
||||
QShader &operator=(const QShader &other);
|
||||
~QShader();
|
||||
void detach();
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
Stage stage() const;
|
||||
void setStage(Stage stage);
|
||||
|
||||
QShaderDescription description() const;
|
||||
void setDescription(const QShaderDescription &desc);
|
||||
|
||||
QList<QShaderKey> availableShaders() const;
|
||||
QShaderCode shader(const QShaderKey &key) const;
|
||||
void setShader(const QShaderKey &key, const QShaderCode &shader);
|
||||
void removeShader(const QShaderKey &key);
|
||||
|
||||
QByteArray serialized(SerializedFormatVersion version = SerializedFormatVersion::Latest) const;
|
||||
static QShader fromSerialized(const QByteArray &data);
|
||||
|
||||
using NativeResourceBindingMap = QMap<int, QPair<int, int> >; // binding -> native_binding[, native_binding]
|
||||
NativeResourceBindingMap nativeResourceBindingMap(const QShaderKey &key) const;
|
||||
void setResourceBindingMap(const QShaderKey &key, const NativeResourceBindingMap &map);
|
||||
void removeResourceBindingMap(const QShaderKey &key);
|
||||
|
||||
struct SeparateToCombinedImageSamplerMapping {
|
||||
QByteArray combinedSamplerName;
|
||||
int textureBinding;
|
||||
int samplerBinding;
|
||||
};
|
||||
using SeparateToCombinedImageSamplerMappingList = QList<SeparateToCombinedImageSamplerMapping>;
|
||||
SeparateToCombinedImageSamplerMappingList separateToCombinedImageSamplerMappingList(const QShaderKey &key) const;
|
||||
void setSeparateToCombinedImageSamplerMappingList(const QShaderKey &key,
|
||||
const SeparateToCombinedImageSamplerMappingList &list);
|
||||
void removeSeparateToCombinedImageSamplerMappingList(const QShaderKey &key);
|
||||
|
||||
struct NativeShaderInfo {
|
||||
int flags = 0;
|
||||
QMap<int, int> extraBufferBindings;
|
||||
};
|
||||
NativeShaderInfo nativeShaderInfo(const QShaderKey &key) const;
|
||||
void setNativeShaderInfo(const QShaderKey &key, const NativeShaderInfo &info);
|
||||
void removeNativeShaderInfo(const QShaderKey &key);
|
||||
|
||||
private:
|
||||
QShaderPrivate *d;
|
||||
friend struct QShaderPrivate;
|
||||
friend Q_GUI_EXPORT bool operator==(const QShader &, const QShader &) noexcept;
|
||||
friend Q_GUI_EXPORT size_t qHash(const QShader &, size_t) noexcept;
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QShader &);
|
||||
#endif
|
||||
};
|
||||
|
||||
class Q_GUI_EXPORT QShaderKey
|
||||
{
|
||||
public:
|
||||
QShaderKey() = default;
|
||||
QShaderKey(QShader::Source s,
|
||||
const QShaderVersion &sver,
|
||||
QShader::Variant svar = QShader::StandardShader);
|
||||
|
||||
QShader::Source source() const { return m_source; }
|
||||
void setSource(QShader::Source s) { m_source = s; }
|
||||
|
||||
QShaderVersion sourceVersion() const { return m_sourceVersion; }
|
||||
void setSourceVersion(const QShaderVersion &sver) { m_sourceVersion = sver; }
|
||||
|
||||
QShader::Variant sourceVariant() const { return m_sourceVariant; }
|
||||
void setSourceVariant(QShader::Variant svar) { m_sourceVariant = svar; }
|
||||
|
||||
private:
|
||||
QShader::Source m_source = QShader::SpirvShader;
|
||||
QShaderVersion m_sourceVersion;
|
||||
QShader::Variant m_sourceVariant = QShader::StandardShader;
|
||||
};
|
||||
|
||||
Q_DECLARE_TYPEINFO(QShaderKey, Q_RELOCATABLE_TYPE);
|
||||
|
||||
Q_GUI_EXPORT bool operator==(const QShader &lhs, const QShader &rhs) noexcept;
|
||||
Q_GUI_EXPORT size_t qHash(const QShader &s, size_t seed = 0) noexcept;
|
||||
|
||||
inline bool operator!=(const QShader &lhs, const QShader &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
Q_GUI_EXPORT bool operator==(const QShaderVersion &lhs, const QShaderVersion &rhs) noexcept;
|
||||
Q_GUI_EXPORT bool operator<(const QShaderVersion &lhs, const QShaderVersion &rhs) noexcept;
|
||||
Q_GUI_EXPORT bool operator==(const QShaderKey &lhs, const QShaderKey &rhs) noexcept;
|
||||
Q_GUI_EXPORT bool operator<(const QShaderKey &lhs, const QShaderKey &rhs) noexcept;
|
||||
Q_GUI_EXPORT bool operator==(const QShaderCode &lhs, const QShaderCode &rhs) noexcept;
|
||||
|
||||
inline bool operator!=(const QShaderVersion &lhs, const QShaderVersion &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const QShaderKey &lhs, const QShaderKey &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const QShaderCode &lhs, const QShaderCode &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
Q_GUI_EXPORT size_t qHash(const QShaderKey &k, size_t seed = 0) noexcept;
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug, const QShader &);
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QShaderKey &k);
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QShaderVersion &v);
|
||||
#endif
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2019 The Qt Company Ltd.
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QSHADER_P_H
|
||||
@ -15,225 +15,76 @@
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <QtGui/qtguiglobal.h>
|
||||
#include <QtCore/qhash.h>
|
||||
#include <QtCore/qmap.h>
|
||||
#include <private/qshaderdescription_p.h>
|
||||
#include <rhi/qshader.h>
|
||||
#include <QtCore/QAtomicInt>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
struct QShaderPrivate;
|
||||
class QShaderKey;
|
||||
|
||||
#ifdef Q_OS_INTEGRITY
|
||||
class QShaderVersion;
|
||||
size_t qHash(const QShaderVersion &, size_t = 0) noexcept;
|
||||
#endif
|
||||
|
||||
class Q_GUI_EXPORT QShaderVersion
|
||||
struct Q_GUI_EXPORT QShaderPrivate
|
||||
{
|
||||
public:
|
||||
enum Flag {
|
||||
GlslEs = 0x01
|
||||
static const int QSB_VERSION = 9;
|
||||
static const int QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS = 8;
|
||||
static const int QSB_VERSION_WITHOUT_EXTENDED_STORAGE_BUFFER_INFO = 7;
|
||||
static const int QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO = 6;
|
||||
static const int QSB_VERSION_WITHOUT_SEPARATE_IMAGES_AND_SAMPLERS = 5;
|
||||
static const int QSB_VERSION_WITHOUT_VAR_ARRAYDIMS = 4;
|
||||
static const int QSB_VERSION_WITH_CBOR = 3;
|
||||
static const int QSB_VERSION_WITH_BINARY_JSON = 2;
|
||||
static const int QSB_VERSION_WITHOUT_BINDINGS = 1;
|
||||
|
||||
enum MslNativeShaderInfoExtraBufferBindings {
|
||||
MslTessVertIndicesBufferBinding = 0,
|
||||
MslTessVertTescOutputBufferBinding,
|
||||
MslTessTescTessLevelBufferBinding,
|
||||
MslTessTescPatchOutputBufferBinding,
|
||||
MslTessTescParamsBufferBinding,
|
||||
MslTessTescInputBufferBinding,
|
||||
MslBufferSizeBufferBinding
|
||||
};
|
||||
Q_DECLARE_FLAGS(Flags, Flag)
|
||||
|
||||
QShaderVersion() = default;
|
||||
QShaderVersion(int v, Flags f = Flags());
|
||||
QShaderPrivate()
|
||||
: ref(1)
|
||||
{
|
||||
}
|
||||
|
||||
int version() const { return m_version; }
|
||||
void setVersion(int v) { m_version = v; }
|
||||
QShaderPrivate(const QShaderPrivate &other)
|
||||
: ref(1),
|
||||
qsbVersion(other.qsbVersion),
|
||||
stage(other.stage),
|
||||
desc(other.desc),
|
||||
shaders(other.shaders),
|
||||
bindings(other.bindings),
|
||||
combinedImageMap(other.combinedImageMap),
|
||||
nativeShaderInfoMap(other.nativeShaderInfoMap)
|
||||
{
|
||||
}
|
||||
|
||||
Flags flags() const { return m_flags; }
|
||||
void setFlags(Flags f) { m_flags = f; }
|
||||
static QShaderPrivate *get(QShader *s) { return s->d; }
|
||||
static const QShaderPrivate *get(const QShader *s) { return s->d; }
|
||||
static int qtQsbVersion(QShader::SerializedFormatVersion qtVersion) {
|
||||
switch (qtVersion) {
|
||||
case QShader::SerializedFormatVersion::Qt_6_4:
|
||||
return (QShaderPrivate::QSB_VERSION_WITHOUT_SEPARATE_IMAGES_AND_SAMPLERS + 1);
|
||||
case QShader::SerializedFormatVersion::Qt_6_5:
|
||||
return (QShaderPrivate::QSB_VERSION_WITHOUT_EXTENDED_STORAGE_BUFFER_INFO + 1);
|
||||
default:
|
||||
return QShaderPrivate::QSB_VERSION;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
int m_version = 100;
|
||||
Flags m_flags;
|
||||
QAtomicInt ref;
|
||||
int qsbVersion = QSB_VERSION;
|
||||
QShader::Stage stage = QShader::VertexStage;
|
||||
QShaderDescription desc;
|
||||
// QMap not QHash because we need to be able to iterate based on sorted keys
|
||||
QMap<QShaderKey, QShaderCode> shaders;
|
||||
QMap<QShaderKey, QShader::NativeResourceBindingMap> bindings;
|
||||
QMap<QShaderKey, QShader::SeparateToCombinedImageSamplerMappingList> combinedImageMap;
|
||||
QMap<QShaderKey, QShader::NativeShaderInfo> nativeShaderInfoMap;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QShaderVersion::Flags)
|
||||
Q_DECLARE_TYPEINFO(QShaderVersion, Q_RELOCATABLE_TYPE);
|
||||
|
||||
class QShaderCode;
|
||||
Q_GUI_EXPORT size_t qHash(const QShaderCode &, size_t = 0) noexcept;
|
||||
|
||||
class Q_GUI_EXPORT QShaderCode
|
||||
{
|
||||
public:
|
||||
QShaderCode() = default;
|
||||
QShaderCode(const QByteArray &code, const QByteArray &entry = QByteArray());
|
||||
|
||||
QByteArray shader() const { return m_shader; }
|
||||
void setShader(const QByteArray &code) { m_shader = code; }
|
||||
|
||||
QByteArray entryPoint() const { return m_entryPoint; }
|
||||
void setEntryPoint(const QByteArray &entry) { m_entryPoint = entry; }
|
||||
|
||||
private:
|
||||
friend Q_GUI_EXPORT size_t qHash(const QShaderCode &, size_t) noexcept;
|
||||
|
||||
QByteArray m_shader;
|
||||
QByteArray m_entryPoint;
|
||||
};
|
||||
|
||||
Q_DECLARE_TYPEINFO(QShaderCode, Q_RELOCATABLE_TYPE);
|
||||
|
||||
class Q_GUI_EXPORT QShader
|
||||
{
|
||||
public:
|
||||
enum Stage {
|
||||
VertexStage = 0,
|
||||
TessellationControlStage,
|
||||
TessellationEvaluationStage,
|
||||
GeometryStage,
|
||||
FragmentStage,
|
||||
ComputeStage
|
||||
};
|
||||
|
||||
enum Source {
|
||||
SpirvShader = 0,
|
||||
GlslShader,
|
||||
HlslShader,
|
||||
DxbcShader, // fxc
|
||||
MslShader,
|
||||
DxilShader, // dxc
|
||||
MetalLibShader, // xcrun metal + xcrun metallib
|
||||
WgslShader
|
||||
};
|
||||
|
||||
enum Variant {
|
||||
StandardShader = 0,
|
||||
BatchableVertexShader,
|
||||
UInt16IndexedVertexAsComputeShader,
|
||||
UInt32IndexedVertexAsComputeShader,
|
||||
NonIndexedVertexAsComputeShader
|
||||
};
|
||||
|
||||
enum class SerializedFormatVersion {
|
||||
Latest = 0,
|
||||
Qt_6_5,
|
||||
Qt_6_4
|
||||
};
|
||||
|
||||
QShader();
|
||||
QShader(const QShader &other);
|
||||
QShader &operator=(const QShader &other);
|
||||
~QShader();
|
||||
void detach();
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
Stage stage() const;
|
||||
void setStage(Stage stage);
|
||||
|
||||
QShaderDescription description() const;
|
||||
void setDescription(const QShaderDescription &desc);
|
||||
|
||||
QList<QShaderKey> availableShaders() const;
|
||||
QShaderCode shader(const QShaderKey &key) const;
|
||||
void setShader(const QShaderKey &key, const QShaderCode &shader);
|
||||
void removeShader(const QShaderKey &key);
|
||||
|
||||
QByteArray serialized(SerializedFormatVersion version = SerializedFormatVersion::Latest) const;
|
||||
static QShader fromSerialized(const QByteArray &data);
|
||||
|
||||
using NativeResourceBindingMap = QMap<int, QPair<int, int> >; // binding -> native_binding[, native_binding]
|
||||
NativeResourceBindingMap nativeResourceBindingMap(const QShaderKey &key) const;
|
||||
void setResourceBindingMap(const QShaderKey &key, const NativeResourceBindingMap &map);
|
||||
void removeResourceBindingMap(const QShaderKey &key);
|
||||
|
||||
struct SeparateToCombinedImageSamplerMapping {
|
||||
QByteArray combinedSamplerName;
|
||||
int textureBinding;
|
||||
int samplerBinding;
|
||||
};
|
||||
using SeparateToCombinedImageSamplerMappingList = QList<SeparateToCombinedImageSamplerMapping>;
|
||||
SeparateToCombinedImageSamplerMappingList separateToCombinedImageSamplerMappingList(const QShaderKey &key) const;
|
||||
void setSeparateToCombinedImageSamplerMappingList(const QShaderKey &key,
|
||||
const SeparateToCombinedImageSamplerMappingList &list);
|
||||
void removeSeparateToCombinedImageSamplerMappingList(const QShaderKey &key);
|
||||
|
||||
struct NativeShaderInfo {
|
||||
int flags = 0;
|
||||
QMap<int, int> extraBufferBindings;
|
||||
};
|
||||
NativeShaderInfo nativeShaderInfo(const QShaderKey &key) const;
|
||||
void setNativeShaderInfo(const QShaderKey &key, const NativeShaderInfo &info);
|
||||
void removeNativeShaderInfo(const QShaderKey &key);
|
||||
|
||||
private:
|
||||
QShaderPrivate *d;
|
||||
friend struct QShaderPrivate;
|
||||
friend Q_GUI_EXPORT bool operator==(const QShader &, const QShader &) noexcept;
|
||||
friend Q_GUI_EXPORT size_t qHash(const QShader &, size_t) noexcept;
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QShader &);
|
||||
#endif
|
||||
};
|
||||
|
||||
class Q_GUI_EXPORT QShaderKey
|
||||
{
|
||||
public:
|
||||
QShaderKey() = default;
|
||||
QShaderKey(QShader::Source s,
|
||||
const QShaderVersion &sver,
|
||||
QShader::Variant svar = QShader::StandardShader);
|
||||
|
||||
QShader::Source source() const { return m_source; }
|
||||
void setSource(QShader::Source s) { m_source = s; }
|
||||
|
||||
QShaderVersion sourceVersion() const { return m_sourceVersion; }
|
||||
void setSourceVersion(const QShaderVersion &sver) { m_sourceVersion = sver; }
|
||||
|
||||
QShader::Variant sourceVariant() const { return m_sourceVariant; }
|
||||
void setSourceVariant(QShader::Variant svar) { m_sourceVariant = svar; }
|
||||
|
||||
private:
|
||||
QShader::Source m_source = QShader::SpirvShader;
|
||||
QShaderVersion m_sourceVersion;
|
||||
QShader::Variant m_sourceVariant = QShader::StandardShader;
|
||||
};
|
||||
|
||||
Q_DECLARE_TYPEINFO(QShaderKey, Q_RELOCATABLE_TYPE);
|
||||
|
||||
Q_GUI_EXPORT bool operator==(const QShader &lhs, const QShader &rhs) noexcept;
|
||||
Q_GUI_EXPORT size_t qHash(const QShader &s, size_t seed = 0) noexcept;
|
||||
|
||||
inline bool operator!=(const QShader &lhs, const QShader &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
Q_GUI_EXPORT bool operator==(const QShaderVersion &lhs, const QShaderVersion &rhs) noexcept;
|
||||
Q_GUI_EXPORT bool operator<(const QShaderVersion &lhs, const QShaderVersion &rhs) noexcept;
|
||||
Q_GUI_EXPORT bool operator==(const QShaderKey &lhs, const QShaderKey &rhs) noexcept;
|
||||
Q_GUI_EXPORT bool operator<(const QShaderKey &lhs, const QShaderKey &rhs) noexcept;
|
||||
Q_GUI_EXPORT bool operator==(const QShaderCode &lhs, const QShaderCode &rhs) noexcept;
|
||||
|
||||
inline bool operator!=(const QShaderVersion &lhs, const QShaderVersion &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const QShaderKey &lhs, const QShaderKey &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const QShaderCode &lhs, const QShaderCode &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
Q_GUI_EXPORT size_t qHash(const QShaderKey &k, size_t seed = 0) noexcept;
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug, const QShader &);
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QShaderKey &k);
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QShaderVersion &v);
|
||||
#endif
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
@ -1,90 +0,0 @@
|
||||
// Copyright (C) 2019 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QSHADER_P_P_H
|
||||
#define QSHADER_P_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists for the convenience
|
||||
// of a number of Qt sources files. This header file may change from
|
||||
// version to version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "qshader_p.h"
|
||||
#include <QtCore/QAtomicInt>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
struct Q_GUI_EXPORT QShaderPrivate
|
||||
{
|
||||
static const int QSB_VERSION = 9;
|
||||
static const int QSB_VERSION_WITHOUT_INPUT_OUTPUT_INTERFACE_BLOCKS = 8;
|
||||
static const int QSB_VERSION_WITHOUT_EXTENDED_STORAGE_BUFFER_INFO = 7;
|
||||
static const int QSB_VERSION_WITHOUT_NATIVE_SHADER_INFO = 6;
|
||||
static const int QSB_VERSION_WITHOUT_SEPARATE_IMAGES_AND_SAMPLERS = 5;
|
||||
static const int QSB_VERSION_WITHOUT_VAR_ARRAYDIMS = 4;
|
||||
static const int QSB_VERSION_WITH_CBOR = 3;
|
||||
static const int QSB_VERSION_WITH_BINARY_JSON = 2;
|
||||
static const int QSB_VERSION_WITHOUT_BINDINGS = 1;
|
||||
|
||||
enum MslNativeShaderInfoExtraBufferBindings {
|
||||
MslTessVertIndicesBufferBinding = 0,
|
||||
MslTessVertTescOutputBufferBinding,
|
||||
MslTessTescTessLevelBufferBinding,
|
||||
MslTessTescPatchOutputBufferBinding,
|
||||
MslTessTescParamsBufferBinding,
|
||||
MslTessTescInputBufferBinding,
|
||||
MslBufferSizeBufferBinding
|
||||
};
|
||||
|
||||
QShaderPrivate()
|
||||
: ref(1)
|
||||
{
|
||||
}
|
||||
|
||||
QShaderPrivate(const QShaderPrivate &other)
|
||||
: ref(1),
|
||||
qsbVersion(other.qsbVersion),
|
||||
stage(other.stage),
|
||||
desc(other.desc),
|
||||
shaders(other.shaders),
|
||||
bindings(other.bindings),
|
||||
combinedImageMap(other.combinedImageMap),
|
||||
nativeShaderInfoMap(other.nativeShaderInfoMap)
|
||||
{
|
||||
}
|
||||
|
||||
static QShaderPrivate *get(QShader *s) { return s->d; }
|
||||
static const QShaderPrivate *get(const QShader *s) { return s->d; }
|
||||
static int qtQsbVersion(QShader::SerializedFormatVersion qtVersion) {
|
||||
switch (qtVersion) {
|
||||
case QShader::SerializedFormatVersion::Qt_6_4:
|
||||
return (QShaderPrivate::QSB_VERSION_WITHOUT_SEPARATE_IMAGES_AND_SAMPLERS + 1);
|
||||
case QShader::SerializedFormatVersion::Qt_6_5:
|
||||
return (QShaderPrivate::QSB_VERSION_WITHOUT_EXTENDED_STORAGE_BUFFER_INFO + 1);
|
||||
default:
|
||||
return QShaderPrivate::QSB_VERSION;
|
||||
}
|
||||
}
|
||||
|
||||
QAtomicInt ref;
|
||||
int qsbVersion = QSB_VERSION;
|
||||
QShader::Stage stage = QShader::VertexStage;
|
||||
QShaderDescription desc;
|
||||
// QMap not QHash because we need to be able to iterate based on sorted keys
|
||||
QMap<QShaderKey, QShaderCode> shaders;
|
||||
QMap<QShaderKey, QShader::NativeResourceBindingMap> bindings;
|
||||
QMap<QShaderKey, QShader::SeparateToCombinedImageSamplerMappingList> combinedImageMap;
|
||||
QMap<QShaderKey, QShader::NativeShaderInfo> nativeShaderInfoMap;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
@ -1,8 +1,8 @@
|
||||
// Copyright (C) 2019 The Qt Company Ltd.
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include "qshaderdescription_p_p.h"
|
||||
#include "qshader_p_p.h"
|
||||
#include "qshaderdescription_p.h"
|
||||
#include "qshader_p.h"
|
||||
#include <QDebug>
|
||||
#include <QDataStream>
|
||||
#include <QJsonObject>
|
||||
@ -12,11 +12,22 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QShaderDescription
|
||||
\internal
|
||||
\ingroup painting-3D
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
|
||||
\brief Describes the interface of a shader.
|
||||
|
||||
\warning The QRhi family of classes in the Qt Gui module, including QShader
|
||||
and QShaderDescription, offer limited compatibility guarantees. There are
|
||||
no source or binary compatibility guarantees for these classes, meaning the
|
||||
API is only guaranteed to work with the Qt version the application was
|
||||
developed against. Source incompatible changes are however aimed to be kept
|
||||
at a minimum and will only be made in minor releases (6.7, 6.8, and so on).
|
||||
To use these classes in an application, link to
|
||||
\c{Qt::GuiPrivate} (if using CMake), and include the headers with the \c
|
||||
rhi prefix, for example \c{#include <rhi/qshaderdescription.h>}.
|
||||
|
||||
A shader typically has a set of inputs and outputs. A vertex shader for
|
||||
example has a number of input variables and may use one or more uniform
|
||||
buffers to access data (e.g. a modelview matrix) provided by the
|
||||
@ -51,8 +62,6 @@ QT_BEGIN_NAMESPACE
|
||||
float opacity;
|
||||
} ubuf;
|
||||
|
||||
out gl_PerVertex { vec4 gl_Position; };
|
||||
|
||||
void main()
|
||||
{
|
||||
v_color = color;
|
||||
@ -200,28 +209,179 @@ QT_BEGIN_NAMESPACE
|
||||
\value ImageRect
|
||||
\value ImageBuffer
|
||||
\value Struct
|
||||
\value Half
|
||||
\value Half2
|
||||
\value Half3
|
||||
\value Half4
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QShaderDescription::InOutVariable
|
||||
\internal
|
||||
\enum QShaderDescription::ImageFormat
|
||||
Image format.
|
||||
|
||||
\value ImageFormatUnknown
|
||||
\value ImageFormatRgba32f
|
||||
\value ImageFormatRgba16f
|
||||
\value ImageFormatR32f
|
||||
\value ImageFormatRgba8
|
||||
\value ImageFormatRgba8Snorm
|
||||
\value ImageFormatRg32f
|
||||
\value ImageFormatRg16f
|
||||
\value ImageFormatR11fG11fB10f
|
||||
\value ImageFormatR16f
|
||||
\value ImageFormatRgba16
|
||||
\value ImageFormatRgb10A2
|
||||
\value ImageFormatRg16
|
||||
\value ImageFormatRg8
|
||||
\value ImageFormatR16
|
||||
\value ImageFormatR8
|
||||
\value ImageFormatRgba16Snorm
|
||||
\value ImageFormatRg16Snorm
|
||||
\value ImageFormatRg8Snorm
|
||||
\value ImageFormatR16Snorm
|
||||
\value ImageFormatR8Snorm
|
||||
\value ImageFormatRgba32i
|
||||
\value ImageFormatRgba16i
|
||||
\value ImageFormatRgba8i
|
||||
\value ImageFormatR32i
|
||||
\value ImageFormatRg32i
|
||||
\value ImageFormatRg16i
|
||||
\value ImageFormatRg8i
|
||||
\value ImageFormatR16i
|
||||
\value ImageFormatR8i
|
||||
\value ImageFormatRgba32ui
|
||||
\value ImageFormatRgba16ui
|
||||
\value ImageFormatRgba8ui
|
||||
\value ImageFormatR32ui
|
||||
\value ImageFormatRgb10a2ui
|
||||
\value ImageFormatRg32ui
|
||||
\value ImageFormatRg16ui
|
||||
\value ImageFormatRg8ui
|
||||
\value ImageFormatR16ui
|
||||
\value ImageFormatR8ui
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QShaderDescription::ImageFlag
|
||||
Image flags.
|
||||
|
||||
\value ReadOnlyImage
|
||||
\value WriteOnlyImage
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QShaderDescription::QualifierFlag
|
||||
Qualifier flags.
|
||||
|
||||
\value QualifierReadOnly
|
||||
\value QualifierWriteOnly
|
||||
\value QualifierCoherent
|
||||
\value QualifierVolatile
|
||||
\value QualifierRestrict
|
||||
*/
|
||||
|
||||
/*!
|
||||
\struct QShaderDescription::InOutVariable
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
|
||||
\brief Describes an input or output variable in the shader.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QShaderDescription
|
||||
for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QShaderDescription::BlockVariable
|
||||
\internal
|
||||
\variable QShaderDescription::InOutVariable::name
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::InOutVariable::type
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::InOutVariable::location
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::InOutVariable::binding
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::InOutVariable::descriptorSet
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::InOutVariable::imageFormat
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::InOutVariable::imageFlags
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::InOutVariable::arrayDims
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::InOutVariable::perPatch
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::InOutVariable::structMembers
|
||||
*/
|
||||
|
||||
/*!
|
||||
\struct QShaderDescription::BlockVariable
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
|
||||
\brief Describes a member of a uniform or push constant block.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QShaderDescription
|
||||
for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QShaderDescription::UniformBlock
|
||||
\internal
|
||||
\variable QShaderDescription::BlockVariable::name
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::BlockVariable::type
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::BlockVariable::offset
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::BlockVariable::size
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::BlockVariable::arrayDims
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::BlockVariable::arrayStride
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::BlockVariable::matrixStride
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::BlockVariable::matrixIsRowMajor
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::BlockVariable::structMembers
|
||||
*/
|
||||
|
||||
/*!
|
||||
\struct QShaderDescription::UniformBlock
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
|
||||
\brief Describes a uniform block.
|
||||
|
||||
@ -229,22 +389,157 @@ QT_BEGIN_NAMESPACE
|
||||
(like GLSL 120 or GLSL/ES 100), uniform blocks are replaced with ordinary
|
||||
uniforms in a struct. The name of the struct, and so the prefix for the
|
||||
uniforms generated from the block members, is given by structName.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QShaderDescription
|
||||
for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QShaderDescription::PushConstantBlock
|
||||
\internal
|
||||
\variable QShaderDescription::UniformBlock::blockName
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::UniformBlock::structName
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::UniformBlock::size
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::UniformBlock::binding
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::UniformBlock::descriptorSet
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::UniformBlock::members
|
||||
*/
|
||||
|
||||
/*!
|
||||
\struct QShaderDescription::PushConstantBlock
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
|
||||
\brief Describes a push constant block.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QShaderDescription
|
||||
for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QShaderDescription::StorageBlock
|
||||
\internal
|
||||
\variable QShaderDescription::PushConstantBlock::name
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::PushConstantBlock::size
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::PushConstantBlock::members
|
||||
*/
|
||||
|
||||
/*!
|
||||
\struct QShaderDescription::StorageBlock
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
|
||||
\brief Describes a shader storage block.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QShaderDescription
|
||||
for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::StorageBlock::blockName
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::StorageBlock::instanceName
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::StorageBlock::knownSize
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::StorageBlock::binding
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::StorageBlock::descriptorSet
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::StorageBlock::members
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::StorageBlock::runtimeArrayStride
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::StorageBlock::qualifierFlags
|
||||
*/
|
||||
|
||||
/*!
|
||||
\struct QShaderDescription::BuiltinVariable
|
||||
\inmodule QtGui
|
||||
\since 6.6
|
||||
|
||||
\brief Describes a built-in variable.
|
||||
|
||||
\note This a RHI API with limited compatibility guarantees, see \l QShaderDescription
|
||||
for details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::BuiltinVariable::type
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::BuiltinVariable::varType
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QShaderDescription::BuiltinVariable::arrayDims
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QShaderDescription::BuiltinType
|
||||
Built-in variable type.
|
||||
|
||||
\value PositionBuiltin
|
||||
\value PointSizeBuiltin
|
||||
\value ClipDistanceBuiltin
|
||||
\value CullDistanceBuiltin
|
||||
\value VertexIdBuiltin
|
||||
\value InstanceIdBuiltin
|
||||
\value PrimitiveIdBuiltin
|
||||
\value InvocationIdBuiltin
|
||||
\value LayerBuiltin
|
||||
\value ViewportIndexBuiltin
|
||||
\value TessLevelOuterBuiltin
|
||||
\value TessLevelInnerBuiltin
|
||||
\value TessCoordBuiltin
|
||||
\value PatchVerticesBuiltin
|
||||
\value FragCoordBuiltin
|
||||
\value PointCoordBuiltin
|
||||
\value FrontFacingBuiltin
|
||||
\value SampleIdBuiltin
|
||||
\value SamplePositionBuiltin
|
||||
\value SampleMaskBuiltin
|
||||
\value FragDepthBuiltin
|
||||
\value NumWorkGroupsBuiltin
|
||||
\value WorkgroupSizeBuiltin
|
||||
\value WorkgroupIdBuiltin
|
||||
\value LocalInvocationIdBuiltin
|
||||
\value GlobalInvocationIdBuiltin
|
||||
\value LocalInvocationIndexBuiltin
|
||||
\value VertexIndexBuiltin
|
||||
\value InstanceIndexBuiltin
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -267,7 +562,7 @@ void QShaderDescription::detach()
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Constructs a copy of \a other.
|
||||
*/
|
||||
QShaderDescription::QShaderDescription(const QShaderDescription &other)
|
||||
: d(other.d)
|
||||
@ -276,7 +571,7 @@ QShaderDescription::QShaderDescription(const QShaderDescription &other)
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Assigns \a other to this object.
|
||||
*/
|
||||
QShaderDescription &QShaderDescription::operator=(const QShaderDescription &other)
|
||||
{
|
||||
@ -574,7 +869,7 @@ uint QShaderDescription::tessellationOutputVertexCount() const
|
||||
\value UnknownTessellationMode
|
||||
\value TrianglesTessellationMode
|
||||
\value QuadTessellationMode
|
||||
\value IsolinesTessellationMode
|
||||
\value IsolineTessellationMode
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
386
src/gui/rhi/qshaderdescription.h
Normal file
386
src/gui/rhi/qshaderdescription.h
Normal file
@ -0,0 +1,386 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QSHADERDESCRIPTION_H
|
||||
#define QSHADERDESCRIPTION_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is part of the RHI API, with limited compatibility guarantees.
|
||||
// Usage of this API may make your code source and binary incompatible with
|
||||
// future versions of Qt.
|
||||
//
|
||||
|
||||
#include <QtGui/qtguiglobal.h>
|
||||
#include <QtCore/qstring.h>
|
||||
#include <QtCore/qlist.h>
|
||||
#include <array>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
struct QShaderDescriptionPrivate;
|
||||
class QDataStream;
|
||||
|
||||
class Q_GUI_EXPORT QShaderDescription
|
||||
{
|
||||
public:
|
||||
QShaderDescription();
|
||||
QShaderDescription(const QShaderDescription &other);
|
||||
QShaderDescription &operator=(const QShaderDescription &other);
|
||||
~QShaderDescription();
|
||||
void detach();
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
void serialize(QDataStream *stream, int version) const;
|
||||
QByteArray toJson() const;
|
||||
|
||||
static QShaderDescription deserialize(QDataStream *stream, int version);
|
||||
|
||||
enum VariableType {
|
||||
Unknown = 0,
|
||||
|
||||
// do not reorder
|
||||
Float,
|
||||
Vec2,
|
||||
Vec3,
|
||||
Vec4,
|
||||
Mat2,
|
||||
Mat2x3,
|
||||
Mat2x4,
|
||||
Mat3,
|
||||
Mat3x2,
|
||||
Mat3x4,
|
||||
Mat4,
|
||||
Mat4x2,
|
||||
Mat4x3,
|
||||
|
||||
Int,
|
||||
Int2,
|
||||
Int3,
|
||||
Int4,
|
||||
|
||||
Uint,
|
||||
Uint2,
|
||||
Uint3,
|
||||
Uint4,
|
||||
|
||||
Bool,
|
||||
Bool2,
|
||||
Bool3,
|
||||
Bool4,
|
||||
|
||||
Double,
|
||||
Double2,
|
||||
Double3,
|
||||
Double4,
|
||||
DMat2,
|
||||
DMat2x3,
|
||||
DMat2x4,
|
||||
DMat3,
|
||||
DMat3x2,
|
||||
DMat3x4,
|
||||
DMat4,
|
||||
DMat4x2,
|
||||
DMat4x3,
|
||||
|
||||
Sampler1D,
|
||||
Sampler2D,
|
||||
Sampler2DMS,
|
||||
Sampler3D,
|
||||
SamplerCube,
|
||||
Sampler1DArray,
|
||||
Sampler2DArray,
|
||||
Sampler2DMSArray,
|
||||
Sampler3DArray,
|
||||
SamplerCubeArray,
|
||||
SamplerRect,
|
||||
SamplerBuffer,
|
||||
SamplerExternalOES,
|
||||
Sampler,
|
||||
|
||||
Image1D,
|
||||
Image2D,
|
||||
Image2DMS,
|
||||
Image3D,
|
||||
ImageCube,
|
||||
Image1DArray,
|
||||
Image2DArray,
|
||||
Image2DMSArray,
|
||||
Image3DArray,
|
||||
ImageCubeArray,
|
||||
ImageRect,
|
||||
ImageBuffer,
|
||||
|
||||
Struct,
|
||||
|
||||
Half,
|
||||
Half2,
|
||||
Half3,
|
||||
Half4
|
||||
};
|
||||
|
||||
enum ImageFormat {
|
||||
// must match SPIR-V's ImageFormat
|
||||
ImageFormatUnknown = 0,
|
||||
ImageFormatRgba32f = 1,
|
||||
ImageFormatRgba16f = 2,
|
||||
ImageFormatR32f = 3,
|
||||
ImageFormatRgba8 = 4,
|
||||
ImageFormatRgba8Snorm = 5,
|
||||
ImageFormatRg32f = 6,
|
||||
ImageFormatRg16f = 7,
|
||||
ImageFormatR11fG11fB10f = 8,
|
||||
ImageFormatR16f = 9,
|
||||
ImageFormatRgba16 = 10,
|
||||
ImageFormatRgb10A2 = 11,
|
||||
ImageFormatRg16 = 12,
|
||||
ImageFormatRg8 = 13,
|
||||
ImageFormatR16 = 14,
|
||||
ImageFormatR8 = 15,
|
||||
ImageFormatRgba16Snorm = 16,
|
||||
ImageFormatRg16Snorm = 17,
|
||||
ImageFormatRg8Snorm = 18,
|
||||
ImageFormatR16Snorm = 19,
|
||||
ImageFormatR8Snorm = 20,
|
||||
ImageFormatRgba32i = 21,
|
||||
ImageFormatRgba16i = 22,
|
||||
ImageFormatRgba8i = 23,
|
||||
ImageFormatR32i = 24,
|
||||
ImageFormatRg32i = 25,
|
||||
ImageFormatRg16i = 26,
|
||||
ImageFormatRg8i = 27,
|
||||
ImageFormatR16i = 28,
|
||||
ImageFormatR8i = 29,
|
||||
ImageFormatRgba32ui = 30,
|
||||
ImageFormatRgba16ui = 31,
|
||||
ImageFormatRgba8ui = 32,
|
||||
ImageFormatR32ui = 33,
|
||||
ImageFormatRgb10a2ui = 34,
|
||||
ImageFormatRg32ui = 35,
|
||||
ImageFormatRg16ui = 36,
|
||||
ImageFormatRg8ui = 37,
|
||||
ImageFormatR16ui = 38,
|
||||
ImageFormatR8ui = 39
|
||||
};
|
||||
|
||||
enum ImageFlag {
|
||||
ReadOnlyImage = 1 << 0,
|
||||
WriteOnlyImage = 1 << 1
|
||||
};
|
||||
Q_DECLARE_FLAGS(ImageFlags, ImageFlag)
|
||||
|
||||
enum QualifierFlag {
|
||||
QualifierReadOnly = 1 << 0,
|
||||
QualifierWriteOnly = 1 << 1,
|
||||
QualifierCoherent = 1 << 2,
|
||||
QualifierVolatile = 1 << 3,
|
||||
QualifierRestrict = 1 << 4,
|
||||
};
|
||||
Q_DECLARE_FLAGS(QualifierFlags, QualifierFlag)
|
||||
|
||||
// Optional data (like decorations) usually default to an otherwise invalid value (-1 or 0). This is intentional.
|
||||
|
||||
struct BlockVariable {
|
||||
QByteArray name;
|
||||
VariableType type = Unknown;
|
||||
int offset = 0;
|
||||
int size = 0;
|
||||
QList<int> arrayDims;
|
||||
int arrayStride = 0;
|
||||
int matrixStride = 0;
|
||||
bool matrixIsRowMajor = false;
|
||||
QList<BlockVariable> structMembers;
|
||||
};
|
||||
|
||||
struct InOutVariable {
|
||||
QByteArray name;
|
||||
VariableType type = Unknown;
|
||||
int location = -1;
|
||||
int binding = -1;
|
||||
int descriptorSet = -1;
|
||||
ImageFormat imageFormat = ImageFormatUnknown;
|
||||
ImageFlags imageFlags;
|
||||
QList<int> arrayDims;
|
||||
bool perPatch = false;
|
||||
QList<BlockVariable> structMembers;
|
||||
};
|
||||
|
||||
struct UniformBlock {
|
||||
QByteArray blockName;
|
||||
QByteArray structName; // instanceName
|
||||
int size = 0;
|
||||
int binding = -1;
|
||||
int descriptorSet = -1;
|
||||
QList<BlockVariable> members;
|
||||
};
|
||||
|
||||
struct PushConstantBlock {
|
||||
QByteArray name;
|
||||
int size = 0;
|
||||
QList<BlockVariable> members;
|
||||
};
|
||||
|
||||
struct StorageBlock {
|
||||
QByteArray blockName;
|
||||
QByteArray instanceName;
|
||||
int knownSize = 0;
|
||||
int binding = -1;
|
||||
int descriptorSet = -1;
|
||||
QList<BlockVariable> members;
|
||||
int runtimeArrayStride = 0;
|
||||
QualifierFlags qualifierFlags;
|
||||
};
|
||||
|
||||
QList<InOutVariable> inputVariables() const;
|
||||
QList<InOutVariable> outputVariables() const;
|
||||
QList<UniformBlock> uniformBlocks() const;
|
||||
QList<PushConstantBlock> pushConstantBlocks() const;
|
||||
QList<StorageBlock> storageBlocks() const;
|
||||
QList<InOutVariable> combinedImageSamplers() const;
|
||||
QList<InOutVariable> separateImages() const;
|
||||
QList<InOutVariable> separateSamplers() const;
|
||||
QList<InOutVariable> storageImages() const;
|
||||
|
||||
enum BuiltinType {
|
||||
// must match SpvBuiltIn
|
||||
PositionBuiltin = 0,
|
||||
PointSizeBuiltin = 1,
|
||||
ClipDistanceBuiltin = 3,
|
||||
CullDistanceBuiltin = 4,
|
||||
VertexIdBuiltin = 5,
|
||||
InstanceIdBuiltin = 6,
|
||||
PrimitiveIdBuiltin = 7,
|
||||
InvocationIdBuiltin = 8,
|
||||
LayerBuiltin = 9,
|
||||
ViewportIndexBuiltin = 10,
|
||||
TessLevelOuterBuiltin = 11,
|
||||
TessLevelInnerBuiltin = 12,
|
||||
TessCoordBuiltin = 13,
|
||||
PatchVerticesBuiltin = 14,
|
||||
FragCoordBuiltin = 15,
|
||||
PointCoordBuiltin = 16,
|
||||
FrontFacingBuiltin = 17,
|
||||
SampleIdBuiltin = 18,
|
||||
SamplePositionBuiltin = 19,
|
||||
SampleMaskBuiltin = 20,
|
||||
FragDepthBuiltin = 22,
|
||||
NumWorkGroupsBuiltin = 24,
|
||||
WorkgroupSizeBuiltin = 25,
|
||||
WorkgroupIdBuiltin = 26,
|
||||
LocalInvocationIdBuiltin = 27,
|
||||
GlobalInvocationIdBuiltin = 28,
|
||||
LocalInvocationIndexBuiltin = 29,
|
||||
VertexIndexBuiltin = 42,
|
||||
InstanceIndexBuiltin = 43
|
||||
};
|
||||
|
||||
struct BuiltinVariable {
|
||||
BuiltinType type;
|
||||
VariableType varType;
|
||||
QList<int> arrayDims;
|
||||
};
|
||||
|
||||
QList<BuiltinVariable> inputBuiltinVariables() const;
|
||||
QList<BuiltinVariable> outputBuiltinVariables() const;
|
||||
|
||||
std::array<uint, 3> computeShaderLocalSize() const;
|
||||
|
||||
uint tessellationOutputVertexCount() const;
|
||||
|
||||
enum TessellationMode {
|
||||
UnknownTessellationMode,
|
||||
TrianglesTessellationMode,
|
||||
QuadTessellationMode,
|
||||
IsolineTessellationMode
|
||||
};
|
||||
|
||||
TessellationMode tessellationMode() const;
|
||||
|
||||
enum TessellationWindingOrder {
|
||||
UnknownTessellationWindingOrder,
|
||||
CwTessellationWindingOrder,
|
||||
CcwTessellationWindingOrder
|
||||
};
|
||||
|
||||
TessellationWindingOrder tessellationWindingOrder() const;
|
||||
|
||||
enum TessellationPartitioning {
|
||||
UnknownTessellationPartitioning,
|
||||
EqualTessellationPartitioning,
|
||||
FractionalEvenTessellationPartitioning,
|
||||
FractionalOddTessellationPartitioning
|
||||
};
|
||||
|
||||
TessellationPartitioning tessellationPartitioning() const;
|
||||
|
||||
private:
|
||||
QShaderDescriptionPrivate *d;
|
||||
friend struct QShaderDescriptionPrivate;
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription &);
|
||||
#endif
|
||||
friend Q_GUI_EXPORT bool operator==(const QShaderDescription &lhs, const QShaderDescription &rhs) noexcept;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QShaderDescription::ImageFlags)
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QShaderDescription::QualifierFlags)
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription &);
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::InOutVariable &);
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::BlockVariable &);
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::UniformBlock &);
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::PushConstantBlock &);
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::StorageBlock &);
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::BuiltinVariable &);
|
||||
#endif
|
||||
|
||||
Q_GUI_EXPORT bool operator==(const QShaderDescription &lhs, const QShaderDescription &rhs) noexcept;
|
||||
Q_GUI_EXPORT bool operator==(const QShaderDescription::InOutVariable &lhs, const QShaderDescription::InOutVariable &rhs) noexcept;
|
||||
Q_GUI_EXPORT bool operator==(const QShaderDescription::BlockVariable &lhs, const QShaderDescription::BlockVariable &rhs) noexcept;
|
||||
Q_GUI_EXPORT bool operator==(const QShaderDescription::UniformBlock &lhs, const QShaderDescription::UniformBlock &rhs) noexcept;
|
||||
Q_GUI_EXPORT bool operator==(const QShaderDescription::PushConstantBlock &lhs, const QShaderDescription::PushConstantBlock &rhs) noexcept;
|
||||
Q_GUI_EXPORT bool operator==(const QShaderDescription::StorageBlock &lhs, const QShaderDescription::StorageBlock &rhs) noexcept;
|
||||
Q_GUI_EXPORT bool operator==(const QShaderDescription::BuiltinVariable &lhs, const QShaderDescription::BuiltinVariable &rhs) noexcept;
|
||||
|
||||
inline bool operator!=(const QShaderDescription &lhs, const QShaderDescription &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const QShaderDescription::InOutVariable &lhs, const QShaderDescription::InOutVariable &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const QShaderDescription::BlockVariable &lhs, const QShaderDescription::BlockVariable &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const QShaderDescription::UniformBlock &lhs, const QShaderDescription::UniformBlock &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const QShaderDescription::PushConstantBlock &lhs, const QShaderDescription::PushConstantBlock &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const QShaderDescription::StorageBlock &lhs, const QShaderDescription::StorageBlock &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const QShaderDescription::BuiltinVariable &lhs, const QShaderDescription::BuiltinVariable &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
@ -1,8 +1,8 @@
|
||||
// Copyright (C) 2021 The Qt Company Ltd.
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QSHADERDESCRIPTION_H
|
||||
#define QSHADERDESCRIPTION_H
|
||||
#ifndef QSHADERDESCRIPTION_P_H
|
||||
#define QSHADERDESCRIPTION_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
@ -15,376 +15,67 @@
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <QtGui/qtguiglobal.h>
|
||||
#include <QtCore/QString>
|
||||
#include <rhi/qshaderdescription.h>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/private/qglobal_p.h>
|
||||
#include <array>
|
||||
#include <QtCore/QAtomicInt>
|
||||
#include <QtCore/QJsonDocument>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
struct QShaderDescriptionPrivate;
|
||||
class QDataStream;
|
||||
|
||||
class Q_GUI_EXPORT QShaderDescription
|
||||
struct Q_GUI_EXPORT QShaderDescriptionPrivate
|
||||
{
|
||||
public:
|
||||
QShaderDescription();
|
||||
QShaderDescription(const QShaderDescription &other);
|
||||
QShaderDescription &operator=(const QShaderDescription &other);
|
||||
~QShaderDescription();
|
||||
void detach();
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
void serialize(QDataStream *stream, int version) const;
|
||||
QByteArray toJson() const;
|
||||
|
||||
static QShaderDescription deserialize(QDataStream *stream, int version);
|
||||
|
||||
enum VariableType {
|
||||
Unknown = 0,
|
||||
|
||||
// do not reorder
|
||||
Float,
|
||||
Vec2,
|
||||
Vec3,
|
||||
Vec4,
|
||||
Mat2,
|
||||
Mat2x3,
|
||||
Mat2x4,
|
||||
Mat3,
|
||||
Mat3x2,
|
||||
Mat3x4,
|
||||
Mat4,
|
||||
Mat4x2,
|
||||
Mat4x3,
|
||||
|
||||
Int,
|
||||
Int2,
|
||||
Int3,
|
||||
Int4,
|
||||
|
||||
Uint,
|
||||
Uint2,
|
||||
Uint3,
|
||||
Uint4,
|
||||
|
||||
Bool,
|
||||
Bool2,
|
||||
Bool3,
|
||||
Bool4,
|
||||
|
||||
Double,
|
||||
Double2,
|
||||
Double3,
|
||||
Double4,
|
||||
DMat2,
|
||||
DMat2x3,
|
||||
DMat2x4,
|
||||
DMat3,
|
||||
DMat3x2,
|
||||
DMat3x4,
|
||||
DMat4,
|
||||
DMat4x2,
|
||||
DMat4x3,
|
||||
|
||||
Sampler1D,
|
||||
Sampler2D,
|
||||
Sampler2DMS,
|
||||
Sampler3D,
|
||||
SamplerCube,
|
||||
Sampler1DArray,
|
||||
Sampler2DArray,
|
||||
Sampler2DMSArray,
|
||||
Sampler3DArray,
|
||||
SamplerCubeArray,
|
||||
SamplerRect,
|
||||
SamplerBuffer,
|
||||
SamplerExternalOES,
|
||||
Sampler,
|
||||
|
||||
Image1D,
|
||||
Image2D,
|
||||
Image2DMS,
|
||||
Image3D,
|
||||
ImageCube,
|
||||
Image1DArray,
|
||||
Image2DArray,
|
||||
Image2DMSArray,
|
||||
Image3DArray,
|
||||
ImageCubeArray,
|
||||
ImageRect,
|
||||
ImageBuffer,
|
||||
|
||||
Struct,
|
||||
|
||||
Half,
|
||||
Half2,
|
||||
Half3,
|
||||
Half4
|
||||
};
|
||||
|
||||
enum ImageFormat {
|
||||
// must match SPIR-V's ImageFormat
|
||||
ImageFormatUnknown = 0,
|
||||
ImageFormatRgba32f = 1,
|
||||
ImageFormatRgba16f = 2,
|
||||
ImageFormatR32f = 3,
|
||||
ImageFormatRgba8 = 4,
|
||||
ImageFormatRgba8Snorm = 5,
|
||||
ImageFormatRg32f = 6,
|
||||
ImageFormatRg16f = 7,
|
||||
ImageFormatR11fG11fB10f = 8,
|
||||
ImageFormatR16f = 9,
|
||||
ImageFormatRgba16 = 10,
|
||||
ImageFormatRgb10A2 = 11,
|
||||
ImageFormatRg16 = 12,
|
||||
ImageFormatRg8 = 13,
|
||||
ImageFormatR16 = 14,
|
||||
ImageFormatR8 = 15,
|
||||
ImageFormatRgba16Snorm = 16,
|
||||
ImageFormatRg16Snorm = 17,
|
||||
ImageFormatRg8Snorm = 18,
|
||||
ImageFormatR16Snorm = 19,
|
||||
ImageFormatR8Snorm = 20,
|
||||
ImageFormatRgba32i = 21,
|
||||
ImageFormatRgba16i = 22,
|
||||
ImageFormatRgba8i = 23,
|
||||
ImageFormatR32i = 24,
|
||||
ImageFormatRg32i = 25,
|
||||
ImageFormatRg16i = 26,
|
||||
ImageFormatRg8i = 27,
|
||||
ImageFormatR16i = 28,
|
||||
ImageFormatR8i = 29,
|
||||
ImageFormatRgba32ui = 30,
|
||||
ImageFormatRgba16ui = 31,
|
||||
ImageFormatRgba8ui = 32,
|
||||
ImageFormatR32ui = 33,
|
||||
ImageFormatRgb10a2ui = 34,
|
||||
ImageFormatRg32ui = 35,
|
||||
ImageFormatRg16ui = 36,
|
||||
ImageFormatRg8ui = 37,
|
||||
ImageFormatR16ui = 38,
|
||||
ImageFormatR8ui = 39
|
||||
};
|
||||
|
||||
enum ImageFlag {
|
||||
ReadOnlyImage = 1 << 0,
|
||||
WriteOnlyImage = 1 << 1
|
||||
};
|
||||
Q_DECLARE_FLAGS(ImageFlags, ImageFlag)
|
||||
|
||||
enum QualifierFlag {
|
||||
QualifierReadOnly = 1 << 0,
|
||||
QualifierWriteOnly = 1 << 1,
|
||||
QualifierCoherent = 1 << 2,
|
||||
QualifierVolatile = 1 << 3,
|
||||
QualifierRestrict = 1 << 4,
|
||||
};
|
||||
Q_DECLARE_FLAGS(QualifierFlags, QualifierFlag)
|
||||
|
||||
// Optional data (like decorations) usually default to an otherwise invalid value (-1 or 0). This is intentional.
|
||||
|
||||
struct BlockVariable
|
||||
QShaderDescriptionPrivate()
|
||||
: ref(1)
|
||||
{
|
||||
QByteArray name;
|
||||
VariableType type = Unknown;
|
||||
int offset = 0;
|
||||
int size = 0;
|
||||
QList<int> arrayDims;
|
||||
int arrayStride = 0;
|
||||
int matrixStride = 0;
|
||||
bool matrixIsRowMajor = false;
|
||||
QList<BlockVariable> structMembers;
|
||||
};
|
||||
}
|
||||
|
||||
struct InOutVariable {
|
||||
QByteArray name;
|
||||
VariableType type = Unknown;
|
||||
int location = -1;
|
||||
int binding = -1;
|
||||
int descriptorSet = -1;
|
||||
ImageFormat imageFormat = ImageFormatUnknown;
|
||||
ImageFlags imageFlags;
|
||||
QList<int> arrayDims;
|
||||
bool perPatch = false;
|
||||
QList<BlockVariable> structMembers;
|
||||
};
|
||||
QShaderDescriptionPrivate(const QShaderDescriptionPrivate &other)
|
||||
: ref(1),
|
||||
inVars(other.inVars),
|
||||
outVars(other.outVars),
|
||||
uniformBlocks(other.uniformBlocks),
|
||||
pushConstantBlocks(other.pushConstantBlocks),
|
||||
storageBlocks(other.storageBlocks),
|
||||
combinedImageSamplers(other.combinedImageSamplers),
|
||||
separateImages(other.separateImages),
|
||||
separateSamplers(other.separateSamplers),
|
||||
storageImages(other.storageImages),
|
||||
inBuiltins(other.inBuiltins),
|
||||
outBuiltins(other.outBuiltins),
|
||||
localSize(other.localSize),
|
||||
tessOutVertCount(other.tessOutVertCount),
|
||||
tessMode(other.tessMode),
|
||||
tessWind(other.tessWind),
|
||||
tessPart(other.tessPart)
|
||||
{
|
||||
}
|
||||
|
||||
struct UniformBlock {
|
||||
QByteArray blockName;
|
||||
QByteArray structName; // instanceName
|
||||
int size = 0;
|
||||
int binding = -1;
|
||||
int descriptorSet = -1;
|
||||
QList<BlockVariable> members;
|
||||
};
|
||||
static QShaderDescriptionPrivate *get(QShaderDescription *desc) { return desc->d; }
|
||||
static const QShaderDescriptionPrivate *get(const QShaderDescription *desc) { return desc->d; }
|
||||
|
||||
struct PushConstantBlock {
|
||||
QByteArray name;
|
||||
int size = 0;
|
||||
QList<BlockVariable> members;
|
||||
};
|
||||
QJsonDocument makeDoc();
|
||||
void writeToStream(QDataStream *stream, int version);
|
||||
void loadFromStream(QDataStream *stream, int version);
|
||||
|
||||
struct StorageBlock {
|
||||
QByteArray blockName;
|
||||
QByteArray instanceName;
|
||||
int knownSize = 0;
|
||||
int binding = -1;
|
||||
int descriptorSet = -1;
|
||||
QList<BlockVariable> members;
|
||||
int runtimeArrayStride = 0;
|
||||
QualifierFlags qualifierFlags;
|
||||
};
|
||||
|
||||
QList<InOutVariable> inputVariables() const;
|
||||
QList<InOutVariable> outputVariables() const;
|
||||
QList<UniformBlock> uniformBlocks() const;
|
||||
QList<PushConstantBlock> pushConstantBlocks() const;
|
||||
QList<StorageBlock> storageBlocks() const;
|
||||
QList<InOutVariable> combinedImageSamplers() const;
|
||||
QList<InOutVariable> separateImages() const;
|
||||
QList<InOutVariable> separateSamplers() const;
|
||||
QList<InOutVariable> storageImages() const;
|
||||
|
||||
enum BuiltinType {
|
||||
// must match SpvBuiltIn
|
||||
PositionBuiltin = 0,
|
||||
PointSizeBuiltin = 1,
|
||||
ClipDistanceBuiltin = 3,
|
||||
CullDistanceBuiltin = 4,
|
||||
VertexIdBuiltin = 5,
|
||||
InstanceIdBuiltin = 6,
|
||||
PrimitiveIdBuiltin = 7,
|
||||
InvocationIdBuiltin = 8,
|
||||
LayerBuiltin = 9,
|
||||
ViewportIndexBuiltin = 10,
|
||||
TessLevelOuterBuiltin = 11,
|
||||
TessLevelInnerBuiltin = 12,
|
||||
TessCoordBuiltin = 13,
|
||||
PatchVerticesBuiltin = 14,
|
||||
FragCoordBuiltin = 15,
|
||||
PointCoordBuiltin = 16,
|
||||
FrontFacingBuiltin = 17,
|
||||
SampleIdBuiltin = 18,
|
||||
SamplePositionBuiltin = 19,
|
||||
SampleMaskBuiltin = 20,
|
||||
FragDepthBuiltin = 22,
|
||||
NumWorkGroupsBuiltin = 24,
|
||||
WorkgroupSizeBuiltin = 25,
|
||||
WorkgroupIdBuiltin = 26,
|
||||
LocalInvocationIdBuiltin = 27,
|
||||
GlobalInvocationIdBuiltin = 28,
|
||||
LocalInvocationIndexBuiltin = 29,
|
||||
VertexIndexBuiltin = 42,
|
||||
InstanceIndexBuiltin = 43
|
||||
};
|
||||
|
||||
struct BuiltinVariable {
|
||||
BuiltinType type;
|
||||
VariableType varType;
|
||||
QList<int> arrayDims;
|
||||
};
|
||||
|
||||
QList<BuiltinVariable> inputBuiltinVariables() const;
|
||||
QList<BuiltinVariable> outputBuiltinVariables() const;
|
||||
|
||||
std::array<uint, 3> computeShaderLocalSize() const;
|
||||
|
||||
uint tessellationOutputVertexCount() const;
|
||||
|
||||
enum TessellationMode {
|
||||
UnknownTessellationMode,
|
||||
TrianglesTessellationMode,
|
||||
QuadTessellationMode,
|
||||
IsolineTessellationMode
|
||||
};
|
||||
|
||||
TessellationMode tessellationMode() const;
|
||||
|
||||
enum TessellationWindingOrder {
|
||||
UnknownTessellationWindingOrder,
|
||||
CwTessellationWindingOrder,
|
||||
CcwTessellationWindingOrder
|
||||
};
|
||||
|
||||
TessellationWindingOrder tessellationWindingOrder() const;
|
||||
|
||||
enum TessellationPartitioning {
|
||||
UnknownTessellationPartitioning,
|
||||
EqualTessellationPartitioning,
|
||||
FractionalEvenTessellationPartitioning,
|
||||
FractionalOddTessellationPartitioning
|
||||
};
|
||||
|
||||
TessellationPartitioning tessellationPartitioning() const;
|
||||
|
||||
private:
|
||||
QShaderDescriptionPrivate *d;
|
||||
friend struct QShaderDescriptionPrivate;
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription &);
|
||||
#endif
|
||||
friend Q_GUI_EXPORT bool operator==(const QShaderDescription &lhs, const QShaderDescription &rhs) noexcept;
|
||||
QAtomicInt ref;
|
||||
QList<QShaderDescription::InOutVariable> inVars;
|
||||
QList<QShaderDescription::InOutVariable> outVars;
|
||||
QList<QShaderDescription::UniformBlock> uniformBlocks;
|
||||
QList<QShaderDescription::PushConstantBlock> pushConstantBlocks;
|
||||
QList<QShaderDescription::StorageBlock> storageBlocks;
|
||||
QList<QShaderDescription::InOutVariable> combinedImageSamplers;
|
||||
QList<QShaderDescription::InOutVariable> separateImages;
|
||||
QList<QShaderDescription::InOutVariable> separateSamplers;
|
||||
QList<QShaderDescription::InOutVariable> storageImages;
|
||||
QList<QShaderDescription::BuiltinVariable> inBuiltins;
|
||||
QList<QShaderDescription::BuiltinVariable> outBuiltins;
|
||||
std::array<uint, 3> localSize = {};
|
||||
uint tessOutVertCount = 0;
|
||||
QShaderDescription::TessellationMode tessMode = QShaderDescription::UnknownTessellationMode;
|
||||
QShaderDescription::TessellationWindingOrder tessWind = QShaderDescription::UnknownTessellationWindingOrder;
|
||||
QShaderDescription::TessellationPartitioning tessPart = QShaderDescription::UnknownTessellationPartitioning;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QShaderDescription::ImageFlags)
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QShaderDescription::QualifierFlags)
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription &);
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::InOutVariable &);
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::BlockVariable &);
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::UniformBlock &);
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::PushConstantBlock &);
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::StorageBlock &);
|
||||
Q_GUI_EXPORT QDebug operator<<(QDebug, const QShaderDescription::BuiltinVariable &);
|
||||
#endif
|
||||
|
||||
Q_GUI_EXPORT bool operator==(const QShaderDescription &lhs, const QShaderDescription &rhs) noexcept;
|
||||
Q_GUI_EXPORT bool operator==(const QShaderDescription::InOutVariable &lhs, const QShaderDescription::InOutVariable &rhs) noexcept;
|
||||
Q_GUI_EXPORT bool operator==(const QShaderDescription::BlockVariable &lhs, const QShaderDescription::BlockVariable &rhs) noexcept;
|
||||
Q_GUI_EXPORT bool operator==(const QShaderDescription::UniformBlock &lhs, const QShaderDescription::UniformBlock &rhs) noexcept;
|
||||
Q_GUI_EXPORT bool operator==(const QShaderDescription::PushConstantBlock &lhs, const QShaderDescription::PushConstantBlock &rhs) noexcept;
|
||||
Q_GUI_EXPORT bool operator==(const QShaderDescription::StorageBlock &lhs, const QShaderDescription::StorageBlock &rhs) noexcept;
|
||||
Q_GUI_EXPORT bool operator==(const QShaderDescription::BuiltinVariable &lhs, const QShaderDescription::BuiltinVariable &rhs) noexcept;
|
||||
|
||||
inline bool operator!=(const QShaderDescription &lhs, const QShaderDescription &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const QShaderDescription::InOutVariable &lhs, const QShaderDescription::InOutVariable &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const QShaderDescription::BlockVariable &lhs, const QShaderDescription::BlockVariable &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const QShaderDescription::UniformBlock &lhs, const QShaderDescription::UniformBlock &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const QShaderDescription::PushConstantBlock &lhs, const QShaderDescription::PushConstantBlock &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const QShaderDescription::StorageBlock &lhs, const QShaderDescription::StorageBlock &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool operator!=(const QShaderDescription::BuiltinVariable &lhs, const QShaderDescription::BuiltinVariable &rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
@ -1,81 +0,0 @@
|
||||
// Copyright (C) 2019 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QSHADERDESCRIPTION_P_H
|
||||
#define QSHADERDESCRIPTION_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists for the convenience
|
||||
// of a number of Qt sources files. This header file may change from
|
||||
// version to version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "qshaderdescription_p.h"
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QAtomicInt>
|
||||
#include <QtCore/QJsonDocument>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
struct Q_GUI_EXPORT QShaderDescriptionPrivate
|
||||
{
|
||||
QShaderDescriptionPrivate()
|
||||
: ref(1)
|
||||
{
|
||||
}
|
||||
|
||||
QShaderDescriptionPrivate(const QShaderDescriptionPrivate &other)
|
||||
: ref(1),
|
||||
inVars(other.inVars),
|
||||
outVars(other.outVars),
|
||||
uniformBlocks(other.uniformBlocks),
|
||||
pushConstantBlocks(other.pushConstantBlocks),
|
||||
storageBlocks(other.storageBlocks),
|
||||
combinedImageSamplers(other.combinedImageSamplers),
|
||||
separateImages(other.separateImages),
|
||||
separateSamplers(other.separateSamplers),
|
||||
storageImages(other.storageImages),
|
||||
inBuiltins(other.inBuiltins),
|
||||
outBuiltins(other.outBuiltins),
|
||||
localSize(other.localSize),
|
||||
tessOutVertCount(other.tessOutVertCount),
|
||||
tessMode(other.tessMode),
|
||||
tessWind(other.tessWind),
|
||||
tessPart(other.tessPart)
|
||||
{
|
||||
}
|
||||
|
||||
static QShaderDescriptionPrivate *get(QShaderDescription *desc) { return desc->d; }
|
||||
static const QShaderDescriptionPrivate *get(const QShaderDescription *desc) { return desc->d; }
|
||||
|
||||
QJsonDocument makeDoc();
|
||||
void writeToStream(QDataStream *stream, int version);
|
||||
void loadFromStream(QDataStream *stream, int version);
|
||||
|
||||
QAtomicInt ref;
|
||||
QList<QShaderDescription::InOutVariable> inVars;
|
||||
QList<QShaderDescription::InOutVariable> outVars;
|
||||
QList<QShaderDescription::UniformBlock> uniformBlocks;
|
||||
QList<QShaderDescription::PushConstantBlock> pushConstantBlocks;
|
||||
QList<QShaderDescription::StorageBlock> storageBlocks;
|
||||
QList<QShaderDescription::InOutVariable> combinedImageSamplers;
|
||||
QList<QShaderDescription::InOutVariable> separateImages;
|
||||
QList<QShaderDescription::InOutVariable> separateSamplers;
|
||||
QList<QShaderDescription::InOutVariable> storageImages;
|
||||
QList<QShaderDescription::BuiltinVariable> inBuiltins;
|
||||
QList<QShaderDescription::BuiltinVariable> outBuiltins;
|
||||
std::array<uint, 3> localSize = {};
|
||||
uint tessOutVertCount = 0;
|
||||
QShaderDescription::TessellationMode tessMode = QShaderDescription::UnknownTessellationMode;
|
||||
QShaderDescription::TessellationWindingOrder tessWind = QShaderDescription::UnknownTessellationWindingOrder;
|
||||
QShaderDescription::TessellationPartitioning tessPart = QShaderDescription::UnknownTessellationPartitioning;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include "qvulkandefaultinstance_p.h"
|
||||
#include <private/qrhivulkan_p.h>
|
||||
#include <rhi/qrhi.h>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
@ -12,6 +12,7 @@ QT_BEGIN_NAMESPACE
|
||||
/*!
|
||||
\class QVulkanInstance
|
||||
\since 5.10
|
||||
\ingroup painting-3D
|
||||
\inmodule QtGui
|
||||
|
||||
\brief The QVulkanInstance class represents a native Vulkan instance, enabling
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <QtOpenGL/QOpenGLFramebufferObject>
|
||||
#include <QtGui/QOpenGLContext>
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/private/qrhi_p.h>
|
||||
#include <rhi/qrhi.h>
|
||||
#include <qpa/qplatformbackingstore.h>
|
||||
|
||||
#include "qopenglcompositor_p.h"
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <QtGui/QPainter>
|
||||
#include <qpa/qplatformbackingstore.h>
|
||||
#include <private/qwindow_p.h>
|
||||
#include <private/qrhi_p.h>
|
||||
#include <rhi/qrhi.h>
|
||||
|
||||
#include "qopenglcompositorbackingstore_p.h"
|
||||
#include "qopenglcompositor_p.h"
|
||||
|
@ -23,8 +23,7 @@
|
||||
#include <QtWidgets/private/qwidget_p.h>
|
||||
#include <QtWidgets/private/qwidgetrepaintmanager_p.h>
|
||||
|
||||
#include <QtGui/private/qrhi_p.h>
|
||||
#include <QtGui/private/qrhigles2_p.h>
|
||||
#include <rhi/qrhi.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
@ -149,6 +149,8 @@ public:
|
||||
|
||||
const std::string &qpaIncludeDir() const { return m_qpaIncludeDir; }
|
||||
|
||||
const std::string &rhiIncludeDir() const { return m_rhiIncludeDir; }
|
||||
|
||||
const std::string &stagingDir() const { return m_stagingDir; }
|
||||
|
||||
const std::string &versionScriptFile() const { return m_versionScriptFile; }
|
||||
@ -157,6 +159,8 @@ public:
|
||||
|
||||
const std::regex &qpaHeadersRegex() const { return m_qpaHeadersRegex; }
|
||||
|
||||
const std::regex &rhiHeadersRegex() const { return m_rhiHeadersRegex; }
|
||||
|
||||
const std::regex &privateHeadersRegex() const { return m_privateHeadersRegex; }
|
||||
|
||||
const std::regex &publicNamespaceRegex() const { return m_publicNamespaceRegex; }
|
||||
@ -188,9 +192,9 @@ public:
|
||||
void printHelp() const
|
||||
{
|
||||
std::cout << "Usage: syncqt -sourceDir <dir> -binaryDir <dir> -module <module name>"
|
||||
" -includeDir <dir> -privateIncludeDir <dir> -qpaIncludeDir <dir>"
|
||||
" -includeDir <dir> -privateIncludeDir <dir> -qpaIncludeDir <dir> -rhiIncludeDir <dir>"
|
||||
" -stagingDir <dir> <-headers <header list>|-all> [-debug]"
|
||||
" [-versionScript <path>] [-qpaHeadersFilter <regex>]"
|
||||
" [-versionScript <path>] [-qpaHeadersFilter <regex>] [-rhiHeadersFilter <regex>]"
|
||||
" [-framework [-frameworkIncludeDir <dir>]]"
|
||||
" [-knownModules <module1> <module2>... <moduleN>]"
|
||||
" [-nonQt] [-internal] [-copy]\n"
|
||||
@ -212,6 +216,8 @@ public:
|
||||
" generated private header files.\n"
|
||||
" -qpaIncludeDir Module include directory for the \n"
|
||||
" generated QPA header files.\n"
|
||||
" -rhiIncludeDir Module include directory for the \n"
|
||||
" generated RHI header files.\n"
|
||||
" -stagingDir Temporary staging directory to collect\n"
|
||||
" artifacts that need to be installed.\n"
|
||||
" -knownModules list of known modules. syncqt uses the\n"
|
||||
@ -225,6 +231,8 @@ public:
|
||||
" from the list of 'headers'.\n"
|
||||
" -qpaHeadersFilter Regex that filters qpa header files from.\n"
|
||||
" the list of 'headers'.\n"
|
||||
" -rhiHeadersFilter Regex that filters rhi header files from.\n"
|
||||
" the list of 'headers'.\n"
|
||||
" -publicNamespaceFilter Symbols that are in the specified\n"
|
||||
" namespace.\n"
|
||||
" are treated as public symbols.\n"
|
||||
@ -262,6 +270,7 @@ private:
|
||||
[[nodiscard]] bool parseArguments(int argc, char *argv[])
|
||||
{
|
||||
std::string qpaHeadersFilter;
|
||||
std::string rhiHeadersFilter;
|
||||
std::string privateHeadersFilter;
|
||||
std::string publicNamespaceFilter;
|
||||
static std::unordered_map<std::string, CommandLineOption<std::string>> stringArgumentMap = {
|
||||
@ -270,9 +279,11 @@ private:
|
||||
{ "-binaryDir", { &m_binaryDir } },
|
||||
{ "-privateHeadersFilter", { &privateHeadersFilter, true } },
|
||||
{ "-qpaHeadersFilter", { &qpaHeadersFilter, true } },
|
||||
{ "-rhiHeadersFilter", { &rhiHeadersFilter, true } },
|
||||
{ "-includeDir", { &m_includeDir } },
|
||||
{ "-privateIncludeDir", { &m_privateIncludeDir } },
|
||||
{ "-qpaIncludeDir", { &m_qpaIncludeDir } },
|
||||
{ "-rhiIncludeDir", { &m_rhiIncludeDir } },
|
||||
{ "-stagingDir", { &m_stagingDir, true } },
|
||||
{ "-versionScript", { &m_versionScriptFile, true } },
|
||||
{ "-frameworkIncludeDir", { &m_frameworkIncludeDir, true } },
|
||||
@ -386,6 +397,9 @@ private:
|
||||
if (!qpaHeadersFilter.empty())
|
||||
m_qpaHeadersRegex = std::regex(qpaHeadersFilter);
|
||||
|
||||
if (!rhiHeadersFilter.empty())
|
||||
m_rhiHeadersRegex = std::regex(rhiHeadersFilter);
|
||||
|
||||
if (!privateHeadersFilter.empty())
|
||||
m_privateHeadersRegex = std::regex(privateHeadersFilter);
|
||||
|
||||
@ -418,9 +432,10 @@ private:
|
||||
// Convert all paths from command line to a generic one.
|
||||
void normilizePaths()
|
||||
{
|
||||
static std::array<std::string *, 8> paths = {
|
||||
static std::array<std::string *, 9> paths = {
|
||||
&m_sourceDir, &m_binaryDir, &m_includeDir, &m_privateIncludeDir,
|
||||
&m_qpaIncludeDir, &m_stagingDir, &m_versionScriptFile, &m_frameworkIncludeDir
|
||||
&m_qpaIncludeDir, &m_rhiIncludeDir, &m_stagingDir,
|
||||
&m_versionScriptFile, &m_frameworkIncludeDir
|
||||
};
|
||||
for (auto path : paths) {
|
||||
if (!path->empty())
|
||||
@ -434,6 +449,7 @@ private:
|
||||
std::string m_includeDir;
|
||||
std::string m_privateIncludeDir;
|
||||
std::string m_qpaIncludeDir;
|
||||
std::string m_rhiIncludeDir;
|
||||
std::string m_stagingDir;
|
||||
std::string m_versionScriptFile;
|
||||
std::string m_frameworkIncludeDir;
|
||||
@ -451,6 +467,7 @@ private:
|
||||
bool m_showOnly = false;
|
||||
bool m_warningsAreErrors = false;
|
||||
std::regex m_qpaHeadersRegex;
|
||||
std::regex m_rhiHeadersRegex;
|
||||
std::regex m_privateHeadersRegex;
|
||||
std::regex m_publicNamespaceRegex;
|
||||
|
||||
@ -522,7 +539,7 @@ class SyncScanner
|
||||
size_t m_currentFileLineNumber = 0;
|
||||
bool m_currentFileInSourceDir = false;
|
||||
|
||||
enum FileType { PublicHeader = 0, PrivateHeader = 1, QpaHeader = 2, ExportHeader = 4 };
|
||||
enum FileType { PublicHeader = 0, PrivateHeader = 1, QpaHeader = 2, ExportHeader = 4, RhiHeader = 8 };
|
||||
unsigned int m_currentFileType = PublicHeader;
|
||||
|
||||
int m_criticalChecks = CriticalChecks;
|
||||
@ -725,6 +742,9 @@ public:
|
||||
if (isHeaderQpa(m_currentFilename))
|
||||
m_currentFileType = QpaHeader | PrivateHeader;
|
||||
|
||||
if (isHeaderRhi(m_currentFilename))
|
||||
m_currentFileType = RhiHeader | PrivateHeader;
|
||||
|
||||
if (std::regex_match(m_currentFilename, ExportsHeaderRegex))
|
||||
m_currentFileType |= ExportHeader;
|
||||
}
|
||||
@ -762,12 +782,14 @@ public:
|
||||
|
||||
bool isPrivate = m_currentFileType & PrivateHeader;
|
||||
bool isQpa = m_currentFileType & QpaHeader;
|
||||
bool isRhi = m_currentFileType & RhiHeader;
|
||||
bool isExport = m_currentFileType & ExportHeader;
|
||||
scannerDebug()
|
||||
<< "processHeader:start: " << headerFile
|
||||
<< " m_currentFilename: " << m_currentFilename
|
||||
<< " isPrivate: " << isPrivate
|
||||
<< " isQpa: " << isQpa
|
||||
<< " isRhi: " << isRhi
|
||||
<< std::endl;
|
||||
|
||||
// Chose the directory where to generate the header aliases or to copy header file if
|
||||
@ -775,6 +797,8 @@ public:
|
||||
std::string outputDir = m_commandLineArgs->includeDir();
|
||||
if (isQpa)
|
||||
outputDir = m_commandLineArgs->qpaIncludeDir();
|
||||
else if (isRhi)
|
||||
outputDir = m_commandLineArgs->rhiIncludeDir();
|
||||
else if (isPrivate)
|
||||
outputDir = m_commandLineArgs->privateIncludeDir();
|
||||
|
||||
@ -826,7 +850,7 @@ public:
|
||||
unsigned int skipChecks = m_commandLineArgs->scanAllMode() ? AllChecks : NoChecks;
|
||||
|
||||
// Collect checks that should skipped for the header file.
|
||||
if (m_commandLineArgs->isNonQtModule() || is3rdParty || isQpa
|
||||
if (m_commandLineArgs->isNonQtModule() || is3rdParty || isQpa || isRhi
|
||||
|| !m_currentFileInSourceDir || isGenerated) {
|
||||
skipChecks = AllChecks;
|
||||
} else {
|
||||
@ -847,7 +871,7 @@ public:
|
||||
|
||||
ParsingResult parsingResult;
|
||||
parsingResult.masterInclude = m_currentFileInSourceDir && !isExport && !is3rdParty
|
||||
&& !isQpa && !isPrivate && !isGenerated;
|
||||
&& !isQpa && !isRhi && !isPrivate && !isGenerated;
|
||||
if (!parseHeader(headerFile, parsingResult, skipChecks)) {
|
||||
scannerDebug() << "parseHeader failed: " << headerFile << std::endl;
|
||||
return false;
|
||||
@ -864,7 +888,7 @@ public:
|
||||
// Add the '#if QT_CONFIG(<feature>)' check for header files that supposed to be
|
||||
// included into the module master header only if corresponding feature is enabled.
|
||||
bool willBeInModuleMasterHeader = false;
|
||||
if (!isQpa && !isPrivate) {
|
||||
if (!isQpa && !isRhi && !isPrivate) {
|
||||
if (m_currentFilename.find('_') == std::string::npos
|
||||
&& parsingResult.masterInclude) {
|
||||
m_masterHeaderContents[m_currentFilename] = parsingResult.requireConfig;
|
||||
@ -1150,7 +1174,7 @@ public:
|
||||
++linesProcessed;
|
||||
|
||||
bool skipSymbols =
|
||||
(m_currentFileType & PrivateHeader) || (m_currentFileType & QpaHeader);
|
||||
(m_currentFileType & PrivateHeader) || (m_currentFileType & QpaHeader) || (m_currentFileType & RhiHeader);
|
||||
|
||||
// Parse pragmas
|
||||
if (std::regex_match(buffer, MacroRegex)) {
|
||||
@ -1331,6 +1355,11 @@ public:
|
||||
return std::regex_match(headerFileName, m_commandLineArgs->qpaHeadersRegex());
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isHeaderRhi(const std::string &headerFileName)
|
||||
{
|
||||
return std::regex_match(headerFileName, m_commandLineArgs->rhiHeadersRegex());
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isHeaderPrivate(const std::string &headerFile)
|
||||
{
|
||||
return std::regex_match(headerFile, m_commandLineArgs->privateHeadersRegex());
|
||||
|
@ -73,6 +73,7 @@
|
||||
);
|
||||
|
||||
@qpa_headers = ( qr/^qplatform/, qr/^qwindowsystem/ );
|
||||
@rhi_headers = ( "qrhi.h", "qrhi_platform.h", "qshader.h", "qshaderdescription.h");
|
||||
my @internal_zlib_headers = ( "crc32.h", "deflate.h", "gzguts.h", "inffast.h", "inffixed.h", "inflate.h", "inftrees.h", "trees.h", "zutil.h" );
|
||||
my @zlib_headers = ( "zconf.h", "zlib.h" );
|
||||
@ignore_headers = ( @internal_zlib_headers );
|
||||
|
@ -9,14 +9,11 @@
|
||||
#include <qrgbafloat.h>
|
||||
#include <qrgba64.h>
|
||||
|
||||
#include <QtGui/private/qrhi_p.h>
|
||||
#include <QtGui/private/qrhi_p_p.h>
|
||||
#include <QtGui/private/qrhinull_p.h>
|
||||
#include <private/qrhi_p.h>
|
||||
|
||||
#if QT_CONFIG(opengl)
|
||||
# include <QOpenGLContext>
|
||||
# include <QOpenGLFunctions>
|
||||
# include <QtGui/private/qrhigles2_p.h>
|
||||
# include <QtGui/private/qguiapplication_p.h>
|
||||
# include <qpa/qplatformintegration.h>
|
||||
# define TST_GL
|
||||
@ -25,19 +22,15 @@
|
||||
#if QT_CONFIG(vulkan)
|
||||
# include <QVulkanInstance>
|
||||
# include <QVulkanFunctions>
|
||||
# include <QtGui/private/qrhivulkan_p.h>
|
||||
# define TST_VK
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <QtGui/private/qrhid3d11_p.h>
|
||||
#include <QtGui/private/qrhid3d12_p.h>
|
||||
# define TST_D3D11
|
||||
# define TST_D3D12
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
|
||||
# include <QtGui/private/qrhimetal_p.h>
|
||||
# define TST_MTL
|
||||
#endif
|
||||
|
||||
|
@ -5,8 +5,8 @@
|
||||
#include <QFile>
|
||||
#include <QBuffer>
|
||||
|
||||
#include <QtGui/private/qshaderdescription_p_p.h>
|
||||
#include <QtGui/private/qshader_p_p.h>
|
||||
#include <private/qshaderdescription_p.h>
|
||||
#include <private/qshader_p.h>
|
||||
|
||||
class tst_QShader : public QObject
|
||||
{
|
||||
|
@ -24,8 +24,7 @@
|
||||
#include <private/qguiapplication_p.h>
|
||||
#include <qpa/qplatformbackingstore.h>
|
||||
#include <qpa/qplatformintegration.h>
|
||||
#include <private/qrhi_p.h>
|
||||
#include <private/qrhigles2_p.h>
|
||||
#include <rhi/qrhi.h>
|
||||
|
||||
class tst_QOpenGLWidget : public QObject
|
||||
{
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include "hellowindow.h"
|
||||
#include <QFile>
|
||||
#include <QtGui/private/qshader_p.h>
|
||||
#include <rhi/qshader.h>
|
||||
|
||||
static float vertexData[] = {
|
||||
// Y up (note clipSpaceCorrMatrix in m_proj), CCW
|
||||
|
@ -5,22 +5,8 @@
|
||||
#define WINDOW_H
|
||||
|
||||
#include <QWindow>
|
||||
|
||||
#include <QtGui/private/qrhinull_p.h>
|
||||
#if QT_CONFIG(opengl)
|
||||
#include <QtGui/private/qrhigles2_p.h>
|
||||
#include <QOffscreenSurface>
|
||||
#endif
|
||||
#if QT_CONFIG(vulkan)
|
||||
#include <QtGui/private/qrhivulkan_p.h>
|
||||
#endif
|
||||
#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)
|
||||
#include <QtGui/private/qrhimetal_p.h>
|
||||
#endif
|
||||
#include <rhi/qrhi.h>
|
||||
|
||||
class Window : public QWindow
|
||||
{
|
||||
|
@ -13,33 +13,17 @@
|
||||
#include <QWindow>
|
||||
#include <QPlatformSurfaceEvent>
|
||||
#include <QElapsedTimer>
|
||||
|
||||
#include <QtGui/private/qshader_p.h>
|
||||
#include <QFile>
|
||||
|
||||
#ifndef QT_NO_OPENGL
|
||||
#include <QtGui/private/qrhigles2_p.h>
|
||||
#include <QOffscreenSurface>
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(vulkan)
|
||||
#include <QLoggingCategory>
|
||||
#include <QtGui/private/qrhivulkan_p.h>
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <QtGui/private/qrhid3d11_p.h>
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
|
||||
#include <QtGui/private/qrhimetal_p.h>
|
||||
#endif
|
||||
#include <QOffscreenSurface>
|
||||
#include <rhi/qrhi.h>
|
||||
|
||||
enum GraphicsApi
|
||||
{
|
||||
OpenGL,
|
||||
Vulkan,
|
||||
D3D11,
|
||||
D3D12,
|
||||
Metal
|
||||
};
|
||||
|
||||
@ -54,6 +38,8 @@ static QString graphicsApiName()
|
||||
return QLatin1String("Vulkan");
|
||||
case D3D11:
|
||||
return QLatin1String("Direct3D 11");
|
||||
case D3D12:
|
||||
return QLatin1String("Direct3D 12");
|
||||
case Metal:
|
||||
return QLatin1String("Metal");
|
||||
default:
|
||||
@ -98,6 +84,10 @@ void createRhi()
|
||||
QRhiD3D11InitParams params;
|
||||
params.enableDebugLayer = true;
|
||||
r.r = QRhi::create(QRhi::D3D11, ¶ms);
|
||||
} else if (graphicsApi == D3D12) {
|
||||
QRhiD3D12InitParams params;
|
||||
params.enableDebugLayer = true;
|
||||
r.r = QRhi::create(QRhi::D3D12, ¶ms);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -281,6 +271,7 @@ Window::Window(const QString &title, const QColor &bgColor, int axis, bool noVSy
|
||||
#endif
|
||||
break;
|
||||
case D3D11:
|
||||
case D3D12:
|
||||
setSurfaceType(Direct3DSurface);
|
||||
break;
|
||||
case Metal:
|
||||
@ -494,6 +485,8 @@ int main(int argc, char **argv)
|
||||
cmdLineParser.addOption(vkOption);
|
||||
QCommandLineOption d3dOption({ "d", "d3d11" }, QLatin1String("Direct3D 11"));
|
||||
cmdLineParser.addOption(d3dOption);
|
||||
QCommandLineOption d3d12Option({ "D", "d3d12" }, QLatin1String("Direct3D 12"));
|
||||
cmdLineParser.addOption(d3d12Option);
|
||||
QCommandLineOption mtlOption({ "m", "metal" }, QLatin1String("Metal"));
|
||||
cmdLineParser.addOption(mtlOption);
|
||||
cmdLineParser.process(app);
|
||||
@ -503,6 +496,8 @@ int main(int argc, char **argv)
|
||||
graphicsApi = Vulkan;
|
||||
if (cmdLineParser.isSet(d3dOption))
|
||||
graphicsApi = D3D11;
|
||||
if (cmdLineParser.isSet(d3d12Option))
|
||||
graphicsApi = D3D12;
|
||||
if (cmdLineParser.isSet(mtlOption))
|
||||
graphicsApi = Metal;
|
||||
|
||||
@ -517,6 +512,7 @@ int main(int argc, char **argv)
|
||||
r.instance = new QVulkanInstance;
|
||||
if (graphicsApi == Vulkan) {
|
||||
r.instance->setLayers({ "VK_LAYER_KHRONOS_validation" });
|
||||
r.instance->setExtensions(QRhiVulkanInitParams::preferredInstanceExtensions());
|
||||
if (!r.instance->create()) {
|
||||
qWarning("Failed to create Vulkan instance, switching to OpenGL");
|
||||
graphicsApi = OpenGL;
|
||||
|
@ -16,27 +16,10 @@
|
||||
#include <QEvent>
|
||||
#include <QCommandLineParser>
|
||||
#include <QElapsedTimer>
|
||||
|
||||
#include <QtGui/private/qshader_p.h>
|
||||
#include <QFile>
|
||||
|
||||
#ifndef QT_NO_OPENGL
|
||||
#include <QtGui/private/qrhigles2_p.h>
|
||||
#include <QOffscreenSurface>
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(vulkan)
|
||||
#include <QLoggingCategory>
|
||||
#include <QtGui/private/qrhivulkan_p.h>
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <QtGui/private/qrhid3d11_p.h>
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
|
||||
#include <QtGui/private/qrhimetal_p.h>
|
||||
#endif
|
||||
#include <QOffscreenSurface>
|
||||
#include <rhi/qrhi.h>
|
||||
|
||||
#ifdef Q_OS_DARWIN
|
||||
#include <QtCore/private/qcore_mac_p.h>
|
||||
@ -66,6 +49,8 @@ static QString graphicsApiName()
|
||||
return QLatin1String("Vulkan");
|
||||
case D3D11:
|
||||
return QLatin1String("Direct3D 11");
|
||||
case D3D12:
|
||||
return QLatin1String("Direct3D 12");
|
||||
case Metal:
|
||||
return QLatin1String("Metal");
|
||||
default:
|
||||
@ -329,6 +314,10 @@ void Renderer::createRhi()
|
||||
QRhiD3D11InitParams params;
|
||||
params.enableDebugLayer = true;
|
||||
r = QRhi::create(QRhi::D3D11, ¶ms, rhiFlags);
|
||||
} else if (graphicsApi == D3D12) {
|
||||
QRhiD3D12InitParams params;
|
||||
params.enableDebugLayer = true;
|
||||
r = QRhi::create(QRhi::D3D12, ¶ms, rhiFlags);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -681,6 +670,8 @@ int main(int argc, char **argv)
|
||||
cmdLineParser.addOption(vkOption);
|
||||
QCommandLineOption d3dOption({ "d", "d3d11" }, QLatin1String("Direct3D 11"));
|
||||
cmdLineParser.addOption(d3dOption);
|
||||
QCommandLineOption d3d12Option({ "D", "d3d12" }, QLatin1String("Direct3D 12"));
|
||||
cmdLineParser.addOption(d3d12Option);
|
||||
QCommandLineOption mtlOption({ "m", "metal" }, QLatin1String("Metal"));
|
||||
cmdLineParser.addOption(mtlOption);
|
||||
cmdLineParser.process(app);
|
||||
@ -690,6 +681,8 @@ int main(int argc, char **argv)
|
||||
graphicsApi = Vulkan;
|
||||
if (cmdLineParser.isSet(d3dOption))
|
||||
graphicsApi = D3D11;
|
||||
if (cmdLineParser.isSet(d3d12Option))
|
||||
graphicsApi = D3D12;
|
||||
if (cmdLineParser.isSet(mtlOption))
|
||||
graphicsApi = Metal;
|
||||
|
||||
|
@ -4,10 +4,6 @@
|
||||
#include "window.h"
|
||||
#include <QPlatformSurfaceEvent>
|
||||
|
||||
#ifndef QT_NO_OPENGL
|
||||
#include <QtGui/private/qrhigles2_p.h>
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(vulkan)
|
||||
extern QVulkanInstance *instance;
|
||||
#endif
|
||||
@ -25,6 +21,7 @@ Window::Window(const QString &title, GraphicsApi api)
|
||||
#endif
|
||||
break;
|
||||
case D3D11:
|
||||
case D3D12:
|
||||
setSurfaceType(Direct3DSurface);
|
||||
break;
|
||||
case Metal:
|
||||
|
@ -11,6 +11,7 @@ enum GraphicsApi
|
||||
OpenGL,
|
||||
Vulkan,
|
||||
D3D11,
|
||||
D3D12,
|
||||
Metal
|
||||
};
|
||||
|
||||
|
@ -7,28 +7,10 @@
|
||||
#include <QFile>
|
||||
#include <QLoggingCategory>
|
||||
#include <QCommandLineParser>
|
||||
#include <QtGui/private/qshader_p.h>
|
||||
|
||||
#include <QtGui/private/qrhinull_p.h>
|
||||
|
||||
#ifndef QT_NO_OPENGL
|
||||
#include <QtGui/private/qrhigles2_p.h>
|
||||
#include <QOffscreenSurface>
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(vulkan)
|
||||
#include <QLoggingCategory>
|
||||
#include <QtGui/private/qrhivulkan_p.h>
|
||||
#endif
|
||||
#include <QOffscreenSurface>
|
||||
|
||||
#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)
|
||||
#include <QtGui/private/qrhimetal_p.h>
|
||||
#endif
|
||||
#include <rhi/qrhi.h>
|
||||
|
||||
//#define TEST_FINISH
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#define EXAMPLEWIDGET_H
|
||||
|
||||
#include "rhiwidget.h"
|
||||
#include <QtGui/private/qrhi_p.h>
|
||||
#include <rhi/qrhi.h>
|
||||
|
||||
class ExampleRhiWidget : public QRhiWidget
|
||||
{
|
||||
|
@ -5,7 +5,7 @@
|
||||
#define RHIWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QtGui/private/qrhi_p.h>
|
||||
#include <rhi/qrhi.h>
|
||||
|
||||
class QRhiWidgetPrivate;
|
||||
|
||||
|
@ -13,28 +13,9 @@
|
||||
#include <QTimer>
|
||||
#include <QLoggingCategory>
|
||||
#include <QColorSpace>
|
||||
|
||||
#include <QtGui/private/qshader_p.h>
|
||||
#include <QFile>
|
||||
#include <QtGui/private/qrhinull_p.h>
|
||||
|
||||
#ifndef QT_NO_OPENGL
|
||||
#include <QtGui/private/qrhigles2_p.h>
|
||||
#include <QOffscreenSurface>
|
||||
#endif
|
||||
|
||||
#if QT_CONFIG(vulkan)
|
||||
#include <QtGui/private/qrhivulkan_p.h>
|
||||
#endif
|
||||
|
||||
#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)
|
||||
#include <QtGui/private/qrhimetal_p.h>
|
||||
#endif
|
||||
#include <rhi/qrhi.h>
|
||||
|
||||
#ifdef EXAMPLEFW_IMGUI
|
||||
#include "qrhiimgui_p.h"
|
||||
|
@ -4,7 +4,7 @@
|
||||
#ifndef QRHIIMGUI_P_H
|
||||
#define QRHIIMGUI_P_H
|
||||
|
||||
#include <QtGui/private/qrhi_p.h>
|
||||
#include <rhi/qrhi.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <QPlatformSurfaceEvent>
|
||||
#include <QTimer>
|
||||
#include <QFile>
|
||||
#include <QtGui/private/qshader_p.h>
|
||||
#include <rhi/qshader.h>
|
||||
#include "../shared/cube.h"
|
||||
|
||||
Window::Window()
|
||||
|
@ -5,8 +5,8 @@
|
||||
#define WINDOW_H
|
||||
|
||||
#include <QWindow>
|
||||
#include <QtGui/private/qrhigles2_p.h>
|
||||
#include <QOffscreenSurface>
|
||||
#include <rhi/qrhi.h>
|
||||
|
||||
class Window : public QWindow
|
||||
{
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include "quadrenderer.h"
|
||||
#include <QFile>
|
||||
#include <QtGui/private/qshader_p.h>
|
||||
#include <rhi/qshader.h>
|
||||
|
||||
// Renders a quad using indexed drawing. No QRhiGraphicsPipeline is created, it
|
||||
// expects to reuse the one created by TriangleRenderer. A separate
|
||||
|
@ -4,7 +4,7 @@
|
||||
#ifndef QUADRENDERER_H
|
||||
#define QUADRENDERER_H
|
||||
|
||||
#include <QtGui/private/qrhi_p.h>
|
||||
#include <rhi/qrhi.h>
|
||||
|
||||
class QuadRenderer
|
||||
{
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include "texturedcuberenderer.h"
|
||||
#include <QFile>
|
||||
#include <QtGui/private/qshader_p.h>
|
||||
#include <rhi/qshader.h>
|
||||
|
||||
#include "../shared/cube.h"
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
#ifndef TEXTUREDCUBERENDERER_H
|
||||
#define TEXTUREDCUBERENDERER_H
|
||||
|
||||
#include <QtGui/private/qrhi_p.h>
|
||||
#include <rhi/qrhi.h>
|
||||
|
||||
class TexturedCubeRenderer
|
||||
{
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include "triangleoncuberenderer.h"
|
||||
#include <QFile>
|
||||
#include <QtGui/private/qshader_p.h>
|
||||
#include <rhi/qshader.h>
|
||||
|
||||
// toggle to test the preserved content (no clear) path
|
||||
const bool IMAGE_UNDER_OFFSCREEN_RENDERING = false;
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include "trianglerenderer.h"
|
||||
#include <QFile>
|
||||
#include <QtGui/private/qshader_p.h>
|
||||
#include <rhi/qshader.h>
|
||||
|
||||
//#define VBUF_IS_DYNAMIC
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
#ifndef TRIANGLERENDERER_H
|
||||
#define TRIANGLERENDERER_H
|
||||
|
||||
#include <QtGui/private/qrhi_p.h>
|
||||
#include <rhi/qrhi.h>
|
||||
|
||||
class TriangleRenderer
|
||||
{
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <QtGui/qguiapplication.h>
|
||||
#include <QtGui/qoffscreensurface.h>
|
||||
#include <QtGui/qpa/qwindowsysteminterface.h>
|
||||
#include <QtGui/private/qrhigles2_p.h>
|
||||
#include <QtGui/rhi/qrhi.h>
|
||||
|
||||
#include <qtwasmtestlib.h>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user