Merge "Merge remote-tracking branch 'origin/5.14' into dev"
This commit is contained in:
commit
0d6e555778
@ -50,10 +50,14 @@ QMAKE_CFLAGS_USE_PRECOMPILE = -include ${QMAKE_PCH_OUTPUT_BASE}
|
|||||||
QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
|
QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
|
||||||
QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE
|
QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE
|
||||||
|
|
||||||
NDK_LLVM_PATH = $$NDK_ROOT/toolchains/llvm/prebuilt/$$NDK_HOST
|
NDK_LLVM_PATH = $$NDK_ROOT/toolchains/llvm/prebuilt/$$NDK_HOST
|
||||||
QMAKE_CC = $$NDK_LLVM_PATH/bin/clang
|
QMAKE_CC = $$NDK_LLVM_PATH/bin/clang
|
||||||
QMAKE_CXX = $$NDK_LLVM_PATH/bin/clang++
|
QMAKE_CXX = $$NDK_LLVM_PATH/bin/clang++
|
||||||
QMAKE_LINK = $$QMAKE_CXX
|
QMAKE_LINK = $$QMAKE_CXX
|
||||||
|
QMAKE_OBJCOPY = $$NDK_LLVM_PATH/bin/llvm-objcopy
|
||||||
|
QMAKE_AR = $$NDK_LLVM_PATH/bin/llvm-ar cqs
|
||||||
|
QMAKE_OBJCOPY = $$NDK_LLVM_PATH/bin/llvm-objcopy
|
||||||
|
QMAKE_NM = $$NDK_LLVM_PATH/bin/llvm-nm -P
|
||||||
|
|
||||||
QMAKE_CFLAGS_OPTIMIZE = -Oz
|
QMAKE_CFLAGS_OPTIMIZE = -Oz
|
||||||
QMAKE_CFLAGS_OPTIMIZE_FULL = -Oz
|
QMAKE_CFLAGS_OPTIMIZE_FULL = -Oz
|
||||||
|
@ -61,14 +61,15 @@ QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD
|
|||||||
QMAKE_LIBS_EGL = -lEGL
|
QMAKE_LIBS_EGL = -lEGL
|
||||||
QMAKE_LIBS_OPENGL_ES2 = -lGLESv2
|
QMAKE_LIBS_OPENGL_ES2 = -lGLESv2
|
||||||
|
|
||||||
# modifications to linux.conf
|
|
||||||
QMAKE_AR = $${CROSS_COMPILE}ar cqs
|
|
||||||
QMAKE_OBJCOPY = $${CROSS_COMPILE}objcopy
|
|
||||||
QMAKE_NM = $${CROSS_COMPILE}nm -P
|
|
||||||
|
|
||||||
QMAKE_STRIP =
|
QMAKE_STRIP =
|
||||||
#$${CROSS_COMPILE}strip
|
#$${CROSS_COMPILE}strip
|
||||||
|
|
||||||
|
|
||||||
|
equals(QT_ARCH, x86): CROSS_COMPILE = $$NDK_LLVM_PATH/bin/i686-linux-android-
|
||||||
|
else: equals(QT_ARCH, x86_64): CROSS_COMPILE = $$NDK_LLVM_PATH/bin/x86_64-linux-android-
|
||||||
|
else: equals(QT_ARCH, arm64-v8a): CROSS_COMPILE = $$NDK_LLVM_PATH/bin/aarch64-linux-android-
|
||||||
|
else: CROSS_COMPILE = $$NDK_LLVM_PATH/bin/arm-linux-androideabi-
|
||||||
|
|
||||||
QMAKE_RANLIB = $${CROSS_COMPILE}ranlib
|
QMAKE_RANLIB = $${CROSS_COMPILE}ranlib
|
||||||
QMAKE_LINK_SHLIB = $$QMAKE_LINK
|
QMAKE_LINK_SHLIB = $$QMAKE_LINK
|
||||||
QMAKE_LFLAGS =
|
QMAKE_LFLAGS =
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
load(resolve_config)
|
load(resolve_config)
|
||||||
|
|
||||||
!host_build:!single_arch:!java:android {
|
!equals(TEMPLATE, aux):!host_build:!single_arch:!java:android {
|
||||||
isEmpty(ANDROID_ABIS): ANDROID_ABIS = $$ALL_ANDROID_ABIS
|
isEmpty(ANDROID_ABIS): ANDROID_ABIS = $$ALL_ANDROID_ABIS
|
||||||
|
|
||||||
ALL_ABIS = $$join(ANDROID_ABIS, _and_)
|
ALL_ABIS = $$join(ANDROID_ABIS, _and_)
|
||||||
|
@ -100,7 +100,7 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
|
|||||||
|
|
||||||
QEventDispatcherWin32Private::QEventDispatcherWin32Private()
|
QEventDispatcherWin32Private::QEventDispatcherWin32Private()
|
||||||
: threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0),
|
: threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0),
|
||||||
wakeUps(0), activateNotifiersPosted(false),
|
getMessageHook(0), wakeUps(0), activateNotifiersPosted(false),
|
||||||
winEventNotifierActivatedEvent(NULL)
|
winEventNotifierActivatedEvent(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -245,9 +245,6 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
|
|||||||
case WM_QT_SENDPOSTEDEVENTS:
|
case WM_QT_SENDPOSTEDEVENTS:
|
||||||
Q_ASSERT(d != 0);
|
Q_ASSERT(d != 0);
|
||||||
|
|
||||||
// Allow posting WM_QT_SENDPOSTEDEVENTS message.
|
|
||||||
d->wakeUps.storeRelaxed(0);
|
|
||||||
|
|
||||||
// We send posted events manually, if the window procedure was invoked
|
// We send posted events manually, if the window procedure was invoked
|
||||||
// by the foreign event loop (e.g. from the native modal dialog).
|
// by the foreign event loop (e.g. from the native modal dialog).
|
||||||
q->sendPostedEvents();
|
q->sendPostedEvents();
|
||||||
@ -257,9 +254,9 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
|
|||||||
return DefWindowProc(hwnd, message, wp, lp);
|
return DefWindowProc(hwnd, message, wp, lp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline UINT inputTimerMask()
|
static inline UINT inputQueueMask()
|
||||||
{
|
{
|
||||||
UINT result = QS_TIMER | QS_INPUT | QS_RAWINPUT;
|
UINT result = QS_ALLEVENTS;
|
||||||
// QTBUG 28513, QTBUG-29097, QTBUG-29435: QS_TOUCH, QS_POINTER became part of
|
// QTBUG 28513, QTBUG-29097, QTBUG-29435: QS_TOUCH, QS_POINTER became part of
|
||||||
// QS_INPUT in Windows Kit 8. They should not be used when running on pre-Windows 8.
|
// QS_INPUT in Windows Kit 8. They should not be used when running on pre-Windows 8.
|
||||||
#if WINVER > 0x0601
|
#if WINVER > 0x0601
|
||||||
@ -269,6 +266,25 @@ static inline UINT inputTimerMask()
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp)
|
||||||
|
{
|
||||||
|
QEventDispatcherWin32 *q = qobject_cast<QEventDispatcherWin32 *>(QAbstractEventDispatcher::instance());
|
||||||
|
Q_ASSERT(q != 0);
|
||||||
|
QEventDispatcherWin32Private *d = q->d_func();
|
||||||
|
MSG *msg = reinterpret_cast<MSG *>(lp);
|
||||||
|
static const UINT mask = inputQueueMask();
|
||||||
|
|
||||||
|
if (HIWORD(GetQueueStatus(mask)) == 0 && wp == PM_REMOVE) {
|
||||||
|
// Allow posting WM_QT_SENDPOSTEDEVENTS message.
|
||||||
|
d->wakeUps.storeRelaxed(0);
|
||||||
|
if (!(msg->hwnd == d->internalHwnd && msg->message == WM_QT_SENDPOSTEDEVENTS)) {
|
||||||
|
PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS,
|
||||||
|
WMWP_QT_TOFOREIGNLOOP, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return d->getMessageHook ? CallNextHookEx(0, code, wp, lp) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Provide class name and atom for the message window used by
|
// Provide class name and atom for the message window used by
|
||||||
// QEventDispatcherWin32Private via Q_GLOBAL_STATIC shared between threads.
|
// QEventDispatcherWin32Private via Q_GLOBAL_STATIC shared between threads.
|
||||||
struct QWindowsMessageWindowClassContext
|
struct QWindowsMessageWindowClassContext
|
||||||
@ -447,6 +463,14 @@ void QEventDispatcherWin32::createInternalHwnd()
|
|||||||
return;
|
return;
|
||||||
d->internalHwnd = qt_create_internal_window(this);
|
d->internalHwnd = qt_create_internal_window(this);
|
||||||
|
|
||||||
|
// setup GetMessage hook needed to drive our posted events
|
||||||
|
d->getMessageHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC) qt_GetMessageHook, NULL, GetCurrentThreadId());
|
||||||
|
if (Q_UNLIKELY(!d->getMessageHook)) {
|
||||||
|
int errorCode = GetLastError();
|
||||||
|
qFatal("Qt: INTERNAL ERROR: failed to install GetMessage hook: %d, %ls",
|
||||||
|
errorCode, qUtf16Printable(qt_error_string(errorCode)));
|
||||||
|
}
|
||||||
|
|
||||||
// start all normal timers
|
// start all normal timers
|
||||||
for (int i = 0; i < d->timerVec.count(); ++i)
|
for (int i = 0; i < d->timerVec.count(); ++i)
|
||||||
d->registerTimer(d->timerVec.at(i));
|
d->registerTimer(d->timerVec.at(i));
|
||||||
@ -499,7 +523,6 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
|
|||||||
|
|
||||||
bool canWait;
|
bool canWait;
|
||||||
bool retVal = false;
|
bool retVal = false;
|
||||||
bool needWM_QT_SENDPOSTEDEVENTS = false;
|
|
||||||
do {
|
do {
|
||||||
DWORD waitRet = 0;
|
DWORD waitRet = 0;
|
||||||
DWORD nCount = 0;
|
DWORD nCount = 0;
|
||||||
@ -549,11 +572,8 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
|
|||||||
if (haveMessage) {
|
if (haveMessage) {
|
||||||
if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) {
|
if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) {
|
||||||
// Set result to 'true', if the message was sent by wakeUp().
|
// Set result to 'true', if the message was sent by wakeUp().
|
||||||
if (msg.wParam == WMWP_QT_FROMWAKEUP) {
|
if (msg.wParam == WMWP_QT_FROMWAKEUP)
|
||||||
d->wakeUps.storeRelaxed(0);
|
|
||||||
retVal = true;
|
retVal = true;
|
||||||
}
|
|
||||||
needWM_QT_SENDPOSTEDEVENTS = true;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (msg.message == WM_TIMER) {
|
if (msg.message == WM_TIMER) {
|
||||||
@ -573,22 +593,10 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!filterNativeEvent(QByteArrayLiteral("windows_generic_MSG"), &msg, 0)) {
|
if (!filterNativeEvent(QByteArrayLiteral("windows_generic_MSG"), &msg, 0)) {
|
||||||
// Post WM_QT_SENDPOSTEDEVENTS before calling external code,
|
|
||||||
// as it can start a foreign event loop.
|
|
||||||
if (needWM_QT_SENDPOSTEDEVENTS) {
|
|
||||||
needWM_QT_SENDPOSTEDEVENTS = false;
|
|
||||||
PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS,
|
|
||||||
WMWP_QT_TOFOREIGNLOOP, 0);
|
|
||||||
}
|
|
||||||
TranslateMessage(&msg);
|
TranslateMessage(&msg);
|
||||||
DispatchMessage(&msg);
|
DispatchMessage(&msg);
|
||||||
}
|
}
|
||||||
} else if (waitRet - WAIT_OBJECT_0 < nCount) {
|
} else if (waitRet - WAIT_OBJECT_0 < nCount) {
|
||||||
if (needWM_QT_SENDPOSTEDEVENTS) {
|
|
||||||
needWM_QT_SENDPOSTEDEVENTS = false;
|
|
||||||
PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS,
|
|
||||||
WMWP_QT_TOFOREIGNLOOP, 0);
|
|
||||||
}
|
|
||||||
activateEventNotifiers();
|
activateEventNotifiers();
|
||||||
} else {
|
} else {
|
||||||
// nothing todo so break
|
// nothing todo so break
|
||||||
@ -606,21 +614,12 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
|
|||||||
waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
|
waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
|
||||||
emit awake();
|
emit awake();
|
||||||
if (waitRet - WAIT_OBJECT_0 < nCount) {
|
if (waitRet - WAIT_OBJECT_0 < nCount) {
|
||||||
if (needWM_QT_SENDPOSTEDEVENTS) {
|
|
||||||
needWM_QT_SENDPOSTEDEVENTS = false;
|
|
||||||
PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS,
|
|
||||||
WMWP_QT_TOFOREIGNLOOP, 0);
|
|
||||||
}
|
|
||||||
activateEventNotifiers();
|
activateEventNotifiers();
|
||||||
retVal = true;
|
retVal = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (canWait);
|
} while (canWait);
|
||||||
|
|
||||||
if (needWM_QT_SENDPOSTEDEVENTS)
|
|
||||||
PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS,
|
|
||||||
WMWP_QT_TOFOREIGNLOOP, 0);
|
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1004,6 +1003,10 @@ void QEventDispatcherWin32::closingDown()
|
|||||||
d->timerDict.clear();
|
d->timerDict.clear();
|
||||||
|
|
||||||
d->closingDown = true;
|
d->closingDown = true;
|
||||||
|
|
||||||
|
if (d->getMessageHook)
|
||||||
|
UnhookWindowsHookEx(d->getMessageHook);
|
||||||
|
d->getMessageHook = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QEventDispatcherWin32::event(QEvent *e)
|
bool QEventDispatcherWin32::event(QEvent *e)
|
||||||
|
@ -113,6 +113,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
friend LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
|
friend LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
|
||||||
|
friend LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int, WPARAM, LPARAM);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QSockNot {
|
struct QSockNot {
|
||||||
@ -166,6 +167,7 @@ public:
|
|||||||
|
|
||||||
// internal window handle used for socketnotifiers/timers/etc
|
// internal window handle used for socketnotifiers/timers/etc
|
||||||
HWND internalHwnd;
|
HWND internalHwnd;
|
||||||
|
HHOOK getMessageHook;
|
||||||
|
|
||||||
// for controlling when to send posted events
|
// for controlling when to send posted events
|
||||||
QAtomicInt wakeUps;
|
QAtomicInt wakeUps;
|
||||||
|
@ -275,6 +275,8 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
|
|||||||
QRhi does not expose APIs for resource barriers or image layout
|
QRhi does not expose APIs for resource barriers or image layout
|
||||||
transitions. Such synchronization is done implicitly by the backends, where
|
transitions. Such synchronization is done implicitly by the backends, where
|
||||||
applicable (for example, Vulkan), by tracking resource usage as necessary.
|
applicable (for example, Vulkan), by tracking resource usage as necessary.
|
||||||
|
Buffer and image barriers are inserted before render or compute passes
|
||||||
|
transparently to the application.
|
||||||
|
|
||||||
\note Resources within a render or compute pass are expected to be bound to
|
\note Resources within a render or compute pass are expected to be bound to
|
||||||
a single usage during that pass. For example, a buffer can be used as
|
a single usage during that pass. For example, a buffer can be used as
|
||||||
@ -554,6 +556,11 @@ Q_LOGGING_CATEGORY(QRHI_LOG_INFO, "qt.rhi.general")
|
|||||||
/*!
|
/*!
|
||||||
\enum QRhi::BeginFrameFlag
|
\enum QRhi::BeginFrameFlag
|
||||||
Flag values for QRhi::beginFrame()
|
Flag values for QRhi::beginFrame()
|
||||||
|
|
||||||
|
\value ExternalContentsInPass Specifies that one or more render or compute
|
||||||
|
passes in this frame will call QRhiCommandBuffer::beginExternal(). Some
|
||||||
|
backends, Vulkan in particular, will fail if this flag is not set and
|
||||||
|
beginExternal() is still called.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -2246,6 +2253,10 @@ QRhiResource::Type QRhiSampler::resourceType() const
|
|||||||
\internal
|
\internal
|
||||||
\inmodule QtGui
|
\inmodule QtGui
|
||||||
\brief Render pass resource.
|
\brief Render pass resource.
|
||||||
|
|
||||||
|
A render pass, if such a concept exists in the underlying graphics API, is
|
||||||
|
a collection of attachments (color, depth, stencil) and describes how those
|
||||||
|
attachments are used.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -2264,6 +2275,18 @@ QRhiResource::Type QRhiRenderPassDescriptor::resourceType() const
|
|||||||
return RenderPassDescriptor;
|
return RenderPassDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\return a pointer to a backend-specific QRhiNativeHandles subclass, such as
|
||||||
|
QRhiVulkanRenderPassNativeHandles. The returned value is null when exposing
|
||||||
|
the underlying native resources is not supported by the backend.
|
||||||
|
|
||||||
|
\sa QRhiVulkanRenderPassNativeHandles
|
||||||
|
*/
|
||||||
|
const QRhiNativeHandles *QRhiRenderPassDescriptor::nativeHandles()
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class QRhiRenderTarget
|
\class QRhiRenderTarget
|
||||||
\internal
|
\internal
|
||||||
@ -4785,6 +4808,11 @@ const QRhiNativeHandles *QRhiCommandBuffer::nativeHandles()
|
|||||||
enqueue commands to the current pass' command buffer by calling graphics
|
enqueue commands to the current pass' command buffer by calling graphics
|
||||||
API functions directly.
|
API functions directly.
|
||||||
|
|
||||||
|
\note This is only available when the intent was declared up front in
|
||||||
|
beginFrame(). Therefore this function must only be called when the frame
|
||||||
|
was started with specifying QRhi::ExternalContentsInPass in the flags
|
||||||
|
passed to QRhi::beginFrame().
|
||||||
|
|
||||||
With Vulkan or Metal one can query the native command buffer or encoder
|
With Vulkan or Metal one can query the native command buffer or encoder
|
||||||
objects via nativeHandles() and enqueue commands to them. With OpenGL or
|
objects via nativeHandles() and enqueue commands to them. With OpenGL or
|
||||||
Direct3D 11 the (device) context can be retrieved from
|
Direct3D 11 the (device) context can be retrieved from
|
||||||
@ -4802,6 +4830,16 @@ const QRhiNativeHandles *QRhiCommandBuffer::nativeHandles()
|
|||||||
functions (\c set* or \c draw*) must be called on the
|
functions (\c set* or \c draw*) must be called on the
|
||||||
QRhiCommandBuffer until endExternal().
|
QRhiCommandBuffer until endExternal().
|
||||||
|
|
||||||
|
\warning Some backends may return a native command buffer object from
|
||||||
|
QRhiCommandBuffer::nativeHandles() that is different from the primary one
|
||||||
|
when inside a beginExternal() - endExternal() block. Therefore it is
|
||||||
|
important to (re)query the native command buffer object after calling
|
||||||
|
beginExternal(). In practical terms this means that with Vulkan for example
|
||||||
|
the externally recorded Vulkan commands are placed onto a secondary command
|
||||||
|
buffer (with VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT).
|
||||||
|
nativeHandles() returns this secondary command buffer when called between
|
||||||
|
begin/endExternal.
|
||||||
|
|
||||||
\sa endExternal(), nativeHandles()
|
\sa endExternal(), nativeHandles()
|
||||||
*/
|
*/
|
||||||
void QRhiCommandBuffer::beginExternal()
|
void QRhiCommandBuffer::beginExternal()
|
||||||
@ -5108,6 +5146,13 @@ QRhiSwapChain *QRhi::newSwapChain()
|
|||||||
/*!
|
/*!
|
||||||
Starts a new frame targeting the next available buffer of \a swapChain.
|
Starts a new frame targeting the next available buffer of \a swapChain.
|
||||||
|
|
||||||
|
A frame consists of resource updates and one or more render and compute
|
||||||
|
passes.
|
||||||
|
|
||||||
|
\a flags can indicate certain special cases. For example, the fact that
|
||||||
|
QRhiCommandBuffer::beginExternal() will be called within this new frame
|
||||||
|
must be declared up front by setting the ExternalContentsInPass flag.
|
||||||
|
|
||||||
The high level pattern of rendering into a QWindow using a swapchain:
|
The high level pattern of rendering into a QWindow using a swapchain:
|
||||||
|
|
||||||
\list
|
\list
|
||||||
@ -5135,9 +5180,7 @@ QRhiSwapChain *QRhi::newSwapChain()
|
|||||||
|
|
||||||
\endlist
|
\endlist
|
||||||
|
|
||||||
\a flags is currently unused.
|
\sa endFrame(), beginOffscreenFrame()
|
||||||
|
|
||||||
\sa endFrame()
|
|
||||||
*/
|
*/
|
||||||
QRhi::FrameOpResult QRhi::beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags)
|
QRhi::FrameOpResult QRhi::beginFrame(QRhiSwapChain *swapChain, BeginFrameFlags flags)
|
||||||
{
|
{
|
||||||
@ -5237,7 +5280,8 @@ int QRhi::currentFrameSlot() const
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
Starts a new offscreen frame. Provides a command buffer suitable for
|
Starts a new offscreen frame. Provides a command buffer suitable for
|
||||||
recording rendering commands in \a cb.
|
recording rendering commands in \a cb. \a flags is used to indicate
|
||||||
|
certain special cases, just like with beginFrame().
|
||||||
|
|
||||||
\note The QRhiCommandBuffer stored to *cb is not owned by the caller.
|
\note The QRhiCommandBuffer stored to *cb is not owned by the caller.
|
||||||
|
|
||||||
@ -5271,14 +5315,14 @@ int QRhi::currentFrameSlot() const
|
|||||||
// image data available in rbResult
|
// image data available in rbResult
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
\sa endOffscreenFrame()
|
\sa endOffscreenFrame(), beginFrame()
|
||||||
*/
|
*/
|
||||||
QRhi::FrameOpResult QRhi::beginOffscreenFrame(QRhiCommandBuffer **cb)
|
QRhi::FrameOpResult QRhi::beginOffscreenFrame(QRhiCommandBuffer **cb, BeginFrameFlags flags)
|
||||||
{
|
{
|
||||||
if (d->inFrame)
|
if (d->inFrame)
|
||||||
qWarning("Attempted to call beginOffscreenFrame() within a still active frame; ignored");
|
qWarning("Attempted to call beginOffscreenFrame() within a still active frame; ignored");
|
||||||
|
|
||||||
QRhi::FrameOpResult r = !d->inFrame ? d->beginOffscreenFrame(cb) : FrameOpSuccess;
|
QRhi::FrameOpResult r = !d->inFrame ? d->beginOffscreenFrame(cb, flags) : FrameOpSuccess;
|
||||||
if (r == FrameOpSuccess)
|
if (r == FrameOpSuccess)
|
||||||
d->inFrame = true;
|
d->inFrame = true;
|
||||||
|
|
||||||
@ -5290,12 +5334,12 @@ QRhi::FrameOpResult QRhi::beginOffscreenFrame(QRhiCommandBuffer **cb)
|
|||||||
|
|
||||||
\sa beginOffscreenFrame()
|
\sa beginOffscreenFrame()
|
||||||
*/
|
*/
|
||||||
QRhi::FrameOpResult QRhi::endOffscreenFrame()
|
QRhi::FrameOpResult QRhi::endOffscreenFrame(EndFrameFlags flags)
|
||||||
{
|
{
|
||||||
if (!d->inFrame)
|
if (!d->inFrame)
|
||||||
qWarning("Attempted to call endOffscreenFrame() without an active frame; ignored");
|
qWarning("Attempted to call endOffscreenFrame() without an active frame; ignored");
|
||||||
|
|
||||||
QRhi::FrameOpResult r = d->inFrame ? d->endOffscreenFrame() : FrameOpSuccess;
|
QRhi::FrameOpResult r = d->inFrame ? d->endOffscreenFrame(flags) : FrameOpSuccess;
|
||||||
d->inFrame = false;
|
d->inFrame = false;
|
||||||
qDeleteAll(d->pendingReleaseAndDestroyResources);
|
qDeleteAll(d->pendingReleaseAndDestroyResources);
|
||||||
d->pendingReleaseAndDestroyResources.clear();
|
d->pendingReleaseAndDestroyResources.clear();
|
||||||
|
@ -843,6 +843,8 @@ class Q_GUI_EXPORT QRhiRenderPassDescriptor : public QRhiResource
|
|||||||
public:
|
public:
|
||||||
QRhiResource::Type resourceType() const override;
|
QRhiResource::Type resourceType() const override;
|
||||||
|
|
||||||
|
virtual const QRhiNativeHandles *nativeHandles();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QRhiRenderPassDescriptor(QRhiImplementation *rhi);
|
QRhiRenderPassDescriptor(QRhiImplementation *rhi);
|
||||||
};
|
};
|
||||||
@ -1324,6 +1326,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum BeginFrameFlag {
|
enum BeginFrameFlag {
|
||||||
|
ExternalContentsInPass = 0x01
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(BeginFrameFlags, BeginFrameFlag)
|
Q_DECLARE_FLAGS(BeginFrameFlags, BeginFrameFlag)
|
||||||
|
|
||||||
@ -1384,8 +1387,8 @@ public:
|
|||||||
bool isRecordingFrame() const;
|
bool isRecordingFrame() const;
|
||||||
int currentFrameSlot() const;
|
int currentFrameSlot() const;
|
||||||
|
|
||||||
FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb);
|
FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, BeginFrameFlags flags = BeginFrameFlags());
|
||||||
FrameOpResult endOffscreenFrame();
|
FrameOpResult endOffscreenFrame(EndFrameFlags flags = EndFrameFlags());
|
||||||
|
|
||||||
QRhi::FrameOpResult finish();
|
QRhi::FrameOpResult finish();
|
||||||
|
|
||||||
|
@ -95,8 +95,8 @@ public:
|
|||||||
virtual QRhiSwapChain *createSwapChain() = 0;
|
virtual QRhiSwapChain *createSwapChain() = 0;
|
||||||
virtual QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) = 0;
|
virtual QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) = 0;
|
||||||
virtual QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) = 0;
|
virtual QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) = 0;
|
||||||
virtual QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb) = 0;
|
virtual QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) = 0;
|
||||||
virtual QRhi::FrameOpResult endOffscreenFrame() = 0;
|
virtual QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) = 0;
|
||||||
virtual QRhi::FrameOpResult finish() = 0;
|
virtual QRhi::FrameOpResult finish() = 0;
|
||||||
|
|
||||||
virtual void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
|
virtual void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) = 0;
|
||||||
|
@ -873,8 +873,10 @@ const QRhiNativeHandles *QRhiD3D11::nativeHandles(QRhiCommandBuffer *cb)
|
|||||||
|
|
||||||
void QRhiD3D11::beginExternal(QRhiCommandBuffer *cb)
|
void QRhiD3D11::beginExternal(QRhiCommandBuffer *cb)
|
||||||
{
|
{
|
||||||
Q_UNUSED(cb);
|
QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
|
||||||
flushCommandBuffer();
|
// no timestampSwapChain, in order to avoid timestamp mess
|
||||||
|
executeCommandBuffer(cbD);
|
||||||
|
cbD->resetCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QRhiD3D11::endExternal(QRhiCommandBuffer *cb)
|
void QRhiD3D11::endExternal(QRhiCommandBuffer *cb)
|
||||||
@ -989,8 +991,9 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
|
|||||||
return QRhi::FrameOpSuccess;
|
return QRhi::FrameOpSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRhi::FrameOpResult QRhiD3D11::beginOffscreenFrame(QRhiCommandBuffer **cb)
|
QRhi::FrameOpResult QRhiD3D11::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(flags);
|
||||||
ofr.active = true;
|
ofr.active = true;
|
||||||
|
|
||||||
ofr.cbWrapper.resetState();
|
ofr.cbWrapper.resetState();
|
||||||
@ -999,8 +1002,9 @@ QRhi::FrameOpResult QRhiD3D11::beginOffscreenFrame(QRhiCommandBuffer **cb)
|
|||||||
return QRhi::FrameOpSuccess;
|
return QRhi::FrameOpSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRhi::FrameOpResult QRhiD3D11::endOffscreenFrame()
|
QRhi::FrameOpResult QRhiD3D11::endOffscreenFrame(QRhi::EndFrameFlags flags)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(flags);
|
||||||
ofr.active = false;
|
ofr.active = false;
|
||||||
|
|
||||||
executeCommandBuffer(&ofr.cbWrapper);
|
executeCommandBuffer(&ofr.cbWrapper);
|
||||||
@ -1135,27 +1139,25 @@ static inline bool isDepthTextureFormat(QRhiTexture::Format format)
|
|||||||
|
|
||||||
QRhi::FrameOpResult QRhiD3D11::finish()
|
QRhi::FrameOpResult QRhiD3D11::finish()
|
||||||
{
|
{
|
||||||
if (inFrame)
|
if (inFrame) {
|
||||||
flushCommandBuffer();
|
if (ofr.active) {
|
||||||
|
Q_ASSERT(!contextState.currentSwapChain);
|
||||||
|
Q_ASSERT(ofr.cbWrapper.recordingPass == QD3D11CommandBuffer::NoPass);
|
||||||
|
executeCommandBuffer(&ofr.cbWrapper);
|
||||||
|
ofr.cbWrapper.resetCommands();
|
||||||
|
} else {
|
||||||
|
Q_ASSERT(contextState.currentSwapChain);
|
||||||
|
Q_ASSERT(contextState.currentSwapChain->cb.recordingPass == QD3D11CommandBuffer::NoPass);
|
||||||
|
executeCommandBuffer(&contextState.currentSwapChain->cb); // no timestampSwapChain, in order to avoid timestamp mess
|
||||||
|
contextState.currentSwapChain->cb.resetCommands();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
finishActiveReadbacks();
|
finishActiveReadbacks();
|
||||||
|
|
||||||
return QRhi::FrameOpSuccess;
|
return QRhi::FrameOpSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QRhiD3D11::flushCommandBuffer()
|
|
||||||
{
|
|
||||||
if (ofr.active) {
|
|
||||||
Q_ASSERT(!contextState.currentSwapChain);
|
|
||||||
executeCommandBuffer(&ofr.cbWrapper);
|
|
||||||
ofr.cbWrapper.resetCommands();
|
|
||||||
} else {
|
|
||||||
Q_ASSERT(contextState.currentSwapChain);
|
|
||||||
executeCommandBuffer(&contextState.currentSwapChain->cb); // no timestampSwapChain, in order to avoid timestamp mess
|
|
||||||
contextState.currentSwapChain->cb.resetCommands();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QRhiD3D11::enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD,
|
void QRhiD3D11::enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD,
|
||||||
int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc)
|
int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc)
|
||||||
{
|
{
|
||||||
|
@ -473,9 +473,9 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
|
|||||||
imageRetainPool.clear();
|
imageRetainPool.clear();
|
||||||
}
|
}
|
||||||
void resetState() {
|
void resetState() {
|
||||||
resetCommands();
|
|
||||||
recordingPass = NoPass;
|
recordingPass = NoPass;
|
||||||
currentTarget = nullptr;
|
currentTarget = nullptr;
|
||||||
|
resetCommands();
|
||||||
resetCachedState();
|
resetCachedState();
|
||||||
}
|
}
|
||||||
void resetCachedState() {
|
void resetCachedState() {
|
||||||
@ -569,8 +569,8 @@ public:
|
|||||||
QRhiSwapChain *createSwapChain() override;
|
QRhiSwapChain *createSwapChain() override;
|
||||||
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
|
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
|
||||||
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
|
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
|
||||||
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb) override;
|
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
|
||||||
QRhi::FrameOpResult endOffscreenFrame() override;
|
QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
|
||||||
QRhi::FrameOpResult finish() override;
|
QRhi::FrameOpResult finish() override;
|
||||||
|
|
||||||
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||||
@ -633,7 +633,6 @@ public:
|
|||||||
void sendVMemStatsToProfiler() override;
|
void sendVMemStatsToProfiler() override;
|
||||||
void makeThreadLocalNativeContextCurrent() override;
|
void makeThreadLocalNativeContextCurrent() override;
|
||||||
|
|
||||||
void flushCommandBuffer();
|
|
||||||
void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD,
|
void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD,
|
||||||
int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc);
|
int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc);
|
||||||
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
|
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
|
||||||
|
@ -1094,15 +1094,36 @@ const QRhiNativeHandles *QRhiGles2::nativeHandles(QRhiCommandBuffer *cb)
|
|||||||
|
|
||||||
void QRhiGles2::beginExternal(QRhiCommandBuffer *cb)
|
void QRhiGles2::beginExternal(QRhiCommandBuffer *cb)
|
||||||
{
|
{
|
||||||
Q_UNUSED(cb);
|
if (ofr.active) {
|
||||||
flushCommandBuffer(); // also ensures the context is current
|
Q_ASSERT(!currentSwapChain);
|
||||||
|
if (!ensureContext())
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
Q_ASSERT(currentSwapChain);
|
||||||
|
if (!ensureContext(currentSwapChain->surface))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb);
|
||||||
|
executeCommandBuffer(cbD);
|
||||||
|
cbD->resetCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QRhiGles2::endExternal(QRhiCommandBuffer *cb)
|
void QRhiGles2::endExternal(QRhiCommandBuffer *cb)
|
||||||
{
|
{
|
||||||
QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb);
|
QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb);
|
||||||
Q_ASSERT(cbD->commands.isEmpty());
|
Q_ASSERT(cbD->commands.isEmpty() && cbD->currentPassResTrackerIndex == -1);
|
||||||
|
|
||||||
cbD->resetCachedState();
|
cbD->resetCachedState();
|
||||||
|
|
||||||
|
if (cbD->recordingPass != QGles2CommandBuffer::NoPass) {
|
||||||
|
// Commands that come after this point need a resource tracker and also
|
||||||
|
// a BarriersForPass command enqueued. (the ones we had from
|
||||||
|
// beginPass() are now gone since beginExternal() processed all that
|
||||||
|
// due to calling executeCommandBuffer()).
|
||||||
|
enqueueBarriersForPass(cbD);
|
||||||
|
}
|
||||||
|
|
||||||
if (cbD->currentTarget)
|
if (cbD->currentTarget)
|
||||||
enqueueBindFramebuffer(cbD->currentTarget, cbD);
|
enqueueBindFramebuffer(cbD->currentTarget, cbD);
|
||||||
}
|
}
|
||||||
@ -1163,8 +1184,9 @@ QRhi::FrameOpResult QRhiGles2::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
|
|||||||
return QRhi::FrameOpSuccess;
|
return QRhi::FrameOpSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRhi::FrameOpResult QRhiGles2::beginOffscreenFrame(QRhiCommandBuffer **cb)
|
QRhi::FrameOpResult QRhiGles2::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(flags);
|
||||||
if (!ensureContext())
|
if (!ensureContext())
|
||||||
return QRhi::FrameOpError;
|
return QRhi::FrameOpError;
|
||||||
|
|
||||||
@ -1179,8 +1201,9 @@ QRhi::FrameOpResult QRhiGles2::beginOffscreenFrame(QRhiCommandBuffer **cb)
|
|||||||
return QRhi::FrameOpSuccess;
|
return QRhi::FrameOpSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRhi::FrameOpResult QRhiGles2::endOffscreenFrame()
|
QRhi::FrameOpResult QRhiGles2::endOffscreenFrame(QRhi::EndFrameFlags flags)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(flags);
|
||||||
Q_ASSERT(ofr.active);
|
Q_ASSERT(ofr.active);
|
||||||
ofr.active = false;
|
ofr.active = false;
|
||||||
|
|
||||||
@ -1196,23 +1219,22 @@ QRhi::FrameOpResult QRhiGles2::endOffscreenFrame()
|
|||||||
|
|
||||||
QRhi::FrameOpResult QRhiGles2::finish()
|
QRhi::FrameOpResult QRhiGles2::finish()
|
||||||
{
|
{
|
||||||
return inFrame ? flushCommandBuffer() : QRhi::FrameOpSuccess;
|
if (inFrame) {
|
||||||
}
|
if (ofr.active) {
|
||||||
|
Q_ASSERT(!currentSwapChain);
|
||||||
QRhi::FrameOpResult QRhiGles2::flushCommandBuffer()
|
Q_ASSERT(ofr.cbWrapper.recordingPass == QGles2CommandBuffer::NoPass);
|
||||||
{
|
if (!ensureContext())
|
||||||
if (ofr.active) {
|
return QRhi::FrameOpError;
|
||||||
Q_ASSERT(!currentSwapChain);
|
executeCommandBuffer(&ofr.cbWrapper);
|
||||||
if (!ensureContext())
|
ofr.cbWrapper.resetCommands();
|
||||||
return QRhi::FrameOpError;
|
} else {
|
||||||
executeCommandBuffer(&ofr.cbWrapper);
|
Q_ASSERT(currentSwapChain);
|
||||||
ofr.cbWrapper.resetCommands();
|
Q_ASSERT(currentSwapChain->cb.recordingPass == QGles2CommandBuffer::NoPass);
|
||||||
} else {
|
if (!ensureContext(currentSwapChain->surface))
|
||||||
Q_ASSERT(currentSwapChain);
|
return QRhi::FrameOpError;
|
||||||
if (!ensureContext(currentSwapChain->surface))
|
executeCommandBuffer(¤tSwapChain->cb);
|
||||||
return QRhi::FrameOpError;
|
currentSwapChain->cb.resetCommands();
|
||||||
executeCommandBuffer(¤tSwapChain->cb);
|
}
|
||||||
currentSwapChain->cb.resetCommands();
|
|
||||||
}
|
}
|
||||||
return QRhi::FrameOpSuccess;
|
return QRhi::FrameOpSuccess;
|
||||||
}
|
}
|
||||||
@ -2483,6 +2505,16 @@ QGles2RenderTargetData *QRhiGles2::enqueueBindFramebuffer(QRhiRenderTarget *rt,
|
|||||||
return rtD;
|
return rtD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QRhiGles2::enqueueBarriersForPass(QGles2CommandBuffer *cbD)
|
||||||
|
{
|
||||||
|
cbD->passResTrackers.append(QRhiPassResourceTracker());
|
||||||
|
cbD->currentPassResTrackerIndex = cbD->passResTrackers.count() - 1;
|
||||||
|
QGles2CommandBuffer::Command cmd;
|
||||||
|
cmd.cmd = QGles2CommandBuffer::Command::BarriersForPass;
|
||||||
|
cmd.args.barriersForPass.trackerIndex = cbD->currentPassResTrackerIndex;
|
||||||
|
cbD->commands.append(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
void QRhiGles2::beginPass(QRhiCommandBuffer *cb,
|
void QRhiGles2::beginPass(QRhiCommandBuffer *cb,
|
||||||
QRhiRenderTarget *rt,
|
QRhiRenderTarget *rt,
|
||||||
const QColor &colorClearValue,
|
const QColor &colorClearValue,
|
||||||
@ -2497,12 +2529,7 @@ void QRhiGles2::beginPass(QRhiCommandBuffer *cb,
|
|||||||
|
|
||||||
// Get a new resource tracker. Then add a command that will generate
|
// Get a new resource tracker. Then add a command that will generate
|
||||||
// glMemoryBarrier() calls based on that tracker when submitted.
|
// glMemoryBarrier() calls based on that tracker when submitted.
|
||||||
cbD->passResTrackers.append(QRhiPassResourceTracker());
|
enqueueBarriersForPass(cbD);
|
||||||
cbD->currentPassResTrackerIndex = cbD->passResTrackers.count() - 1;
|
|
||||||
QGles2CommandBuffer::Command cmd;
|
|
||||||
cmd.cmd = QGles2CommandBuffer::Command::BarriersForPass;
|
|
||||||
cmd.args.barriersForPass.trackerIndex = cbD->currentPassResTrackerIndex;
|
|
||||||
cbD->commands.append(cmd);
|
|
||||||
|
|
||||||
bool wantsColorClear, wantsDsClear;
|
bool wantsColorClear, wantsDsClear;
|
||||||
QGles2RenderTargetData *rtD = enqueueBindFramebuffer(rt, cbD, &wantsColorClear, &wantsDsClear);
|
QGles2RenderTargetData *rtD = enqueueBindFramebuffer(rt, cbD, &wantsColorClear, &wantsDsClear);
|
||||||
@ -2578,12 +2605,7 @@ void QRhiGles2::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch
|
|||||||
if (resourceUpdates)
|
if (resourceUpdates)
|
||||||
enqueueResourceUpdates(cb, resourceUpdates);
|
enqueueResourceUpdates(cb, resourceUpdates);
|
||||||
|
|
||||||
cbD->passResTrackers.append(QRhiPassResourceTracker());
|
enqueueBarriersForPass(cbD);
|
||||||
cbD->currentPassResTrackerIndex = cbD->passResTrackers.count() - 1;
|
|
||||||
QGles2CommandBuffer::Command cmd;
|
|
||||||
cmd.cmd = QGles2CommandBuffer::Command::BarriersForPass;
|
|
||||||
cmd.args.barriersForPass.trackerIndex = cbD->currentPassResTrackerIndex;
|
|
||||||
cbD->commands.append(cmd);
|
|
||||||
|
|
||||||
cbD->recordingPass = QGles2CommandBuffer::ComputePass;
|
cbD->recordingPass = QGles2CommandBuffer::ComputePass;
|
||||||
|
|
||||||
|
@ -525,19 +525,16 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer
|
|||||||
}
|
}
|
||||||
void resetCommands() {
|
void resetCommands() {
|
||||||
commands.clear();
|
commands.clear();
|
||||||
// beginExternal() can lead to calling resetCommands() inside a pass,
|
|
||||||
// hence the condition
|
|
||||||
if (recordingPass == NoPass) {
|
|
||||||
passResTrackers.clear();
|
|
||||||
currentPassResTrackerIndex = -1;
|
|
||||||
}
|
|
||||||
dataRetainPool.clear();
|
dataRetainPool.clear();
|
||||||
imageRetainPool.clear();
|
imageRetainPool.clear();
|
||||||
|
|
||||||
|
passResTrackers.clear();
|
||||||
|
currentPassResTrackerIndex = -1;
|
||||||
}
|
}
|
||||||
void resetState() {
|
void resetState() {
|
||||||
resetCommands();
|
|
||||||
recordingPass = NoPass;
|
recordingPass = NoPass;
|
||||||
currentTarget = nullptr;
|
currentTarget = nullptr;
|
||||||
|
resetCommands();
|
||||||
resetCachedState();
|
resetCachedState();
|
||||||
}
|
}
|
||||||
void resetCachedState() {
|
void resetCachedState() {
|
||||||
@ -605,8 +602,8 @@ public:
|
|||||||
QRhiSwapChain *createSwapChain() override;
|
QRhiSwapChain *createSwapChain() override;
|
||||||
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
|
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
|
||||||
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
|
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
|
||||||
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb) override;
|
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
|
||||||
QRhi::FrameOpResult endOffscreenFrame() override;
|
QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
|
||||||
QRhi::FrameOpResult finish() override;
|
QRhi::FrameOpResult finish() override;
|
||||||
|
|
||||||
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||||
@ -671,7 +668,6 @@ public:
|
|||||||
|
|
||||||
bool ensureContext(QSurface *surface = nullptr) const;
|
bool ensureContext(QSurface *surface = nullptr) const;
|
||||||
void executeDeferredReleases();
|
void executeDeferredReleases();
|
||||||
QRhi::FrameOpResult flushCommandBuffer();
|
|
||||||
void trackedBufferBarrier(QGles2CommandBuffer *cbD, QGles2Buffer *bufD, QGles2Buffer::Access access);
|
void trackedBufferBarrier(QGles2CommandBuffer *cbD, QGles2Buffer *bufD, QGles2Buffer::Access access);
|
||||||
void trackedImageBarrier(QGles2CommandBuffer *cbD, QGles2Texture *texD, QGles2Texture::Access access);
|
void trackedImageBarrier(QGles2CommandBuffer *cbD, QGles2Texture *texD, QGles2Texture::Access access);
|
||||||
void enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cbD,
|
void enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cbD,
|
||||||
@ -692,6 +688,7 @@ public:
|
|||||||
const uint *dynOfsPairs, int dynOfsCount);
|
const uint *dynOfsPairs, int dynOfsCount);
|
||||||
QGles2RenderTargetData *enqueueBindFramebuffer(QRhiRenderTarget *rt, QGles2CommandBuffer *cbD,
|
QGles2RenderTargetData *enqueueBindFramebuffer(QRhiRenderTarget *rt, QGles2CommandBuffer *cbD,
|
||||||
bool *wantsColorClear = nullptr, bool *wantsDsClear = nullptr);
|
bool *wantsColorClear = nullptr, bool *wantsDsClear = nullptr);
|
||||||
|
void enqueueBarriersForPass(QGles2CommandBuffer *cbD);
|
||||||
int effectiveSampleCount(int sampleCount) const;
|
int effectiveSampleCount(int sampleCount) const;
|
||||||
bool compileShader(GLuint program, const QRhiShaderStage &shaderStage,
|
bool compileShader(GLuint program, const QRhiShaderStage &shaderStage,
|
||||||
QShaderDescription *desc, int *glslVersionUsed);
|
QShaderDescription *desc, int *glslVersionUsed);
|
||||||
|
@ -1243,8 +1243,10 @@ QRhi::FrameOpResult QRhiMetal::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
|
|||||||
return QRhi::FrameOpSuccess;
|
return QRhi::FrameOpSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRhi::FrameOpResult QRhiMetal::beginOffscreenFrame(QRhiCommandBuffer **cb)
|
QRhi::FrameOpResult QRhiMetal::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(flags);
|
||||||
|
|
||||||
currentFrameSlot = (currentFrameSlot + 1) % QMTL_FRAMES_IN_FLIGHT;
|
currentFrameSlot = (currentFrameSlot + 1) % QMTL_FRAMES_IN_FLIGHT;
|
||||||
if (swapchains.count() > 1) {
|
if (swapchains.count() > 1) {
|
||||||
for (QMetalSwapChain *sc : qAsConst(swapchains)) {
|
for (QMetalSwapChain *sc : qAsConst(swapchains)) {
|
||||||
@ -1268,8 +1270,9 @@ QRhi::FrameOpResult QRhiMetal::beginOffscreenFrame(QRhiCommandBuffer **cb)
|
|||||||
return QRhi::FrameOpSuccess;
|
return QRhi::FrameOpSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRhi::FrameOpResult QRhiMetal::endOffscreenFrame()
|
QRhi::FrameOpResult QRhiMetal::endOffscreenFrame(QRhi::EndFrameFlags flags)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(flags);
|
||||||
Q_ASSERT(d->ofr.active);
|
Q_ASSERT(d->ofr.active);
|
||||||
d->ofr.active = false;
|
d->ofr.active = false;
|
||||||
|
|
||||||
|
@ -354,8 +354,8 @@ public:
|
|||||||
QRhiSwapChain *createSwapChain() override;
|
QRhiSwapChain *createSwapChain() override;
|
||||||
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
|
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
|
||||||
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
|
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
|
||||||
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb) override;
|
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
|
||||||
QRhi::FrameOpResult endOffscreenFrame() override;
|
QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
|
||||||
QRhi::FrameOpResult finish() override;
|
QRhi::FrameOpResult finish() override;
|
||||||
|
|
||||||
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||||
|
@ -356,14 +356,16 @@ QRhi::FrameOpResult QRhiNull::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameF
|
|||||||
return QRhi::FrameOpSuccess;
|
return QRhi::FrameOpSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRhi::FrameOpResult QRhiNull::beginOffscreenFrame(QRhiCommandBuffer **cb)
|
QRhi::FrameOpResult QRhiNull::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(flags);
|
||||||
*cb = &offscreenCommandBuffer;
|
*cb = &offscreenCommandBuffer;
|
||||||
return QRhi::FrameOpSuccess;
|
return QRhi::FrameOpSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRhi::FrameOpResult QRhiNull::endOffscreenFrame()
|
QRhi::FrameOpResult QRhiNull::endOffscreenFrame(QRhi::EndFrameFlags flags)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(flags);
|
||||||
return QRhi::FrameOpSuccess;
|
return QRhi::FrameOpSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,8 +220,8 @@ public:
|
|||||||
QRhiSwapChain *createSwapChain() override;
|
QRhiSwapChain *createSwapChain() override;
|
||||||
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
|
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
|
||||||
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
|
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
|
||||||
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb) override;
|
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
|
||||||
QRhi::FrameOpResult endOffscreenFrame() override;
|
QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
|
||||||
QRhi::FrameOpResult finish() override;
|
QRhi::FrameOpResult finish() override;
|
||||||
|
|
||||||
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||||
|
@ -58,6 +58,28 @@ QT_BEGIN_NAMESPACE
|
|||||||
and a separate, host visible staging buffer is used to upload data to them.
|
and a separate, host visible staging buffer is used to upload data to them.
|
||||||
"Dynamic" buffers are in host visible memory and are duplicated (since there
|
"Dynamic" buffers are in host visible memory and are duplicated (since there
|
||||||
can be 2 frames in flight). This is handled transparently to the application.
|
can be 2 frames in flight). This is handled transparently to the application.
|
||||||
|
|
||||||
|
Barriers are generated automatically for each render or compute pass, based
|
||||||
|
on the resources that are used in that pass (in QRhiShaderResourceBindings,
|
||||||
|
vertex inputs, etc.). This implies deferring the recording of the command
|
||||||
|
buffer since the barriers have to be placed at the right place (before the
|
||||||
|
pass), and that can only be done once we know all the things the pass does.
|
||||||
|
|
||||||
|
This in turn has implications for integrating external commands
|
||||||
|
(beginExternal() - direct Vulkan calls - endExternal()) because that is
|
||||||
|
incompatible with this approach by nature. Therefore we support another mode
|
||||||
|
of operation, where each render or compute pass uses one or more secondary
|
||||||
|
command buffers (recorded right away), with each beginExternal() leading to
|
||||||
|
closing the current secondary cb, creating a new secondary cb for the
|
||||||
|
external content, and then starting yet another one in endExternal() for
|
||||||
|
whatever comes afterwards in the pass. This way the primary command buffer
|
||||||
|
only has vkCmdExecuteCommand(s) within a renderpass instance
|
||||||
|
(Begin-EndRenderPass). (i.e. our only subpass is then
|
||||||
|
VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS instead of
|
||||||
|
VK_SUBPASS_CONTENTS_INLINE)
|
||||||
|
|
||||||
|
The command buffer management mode is decided on a per frame basis,
|
||||||
|
controlled by the ExternalContentsInPass flag of beginFrame().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -182,6 +204,13 @@ QT_BEGIN_NAMESPACE
|
|||||||
\l{QRhi::endOffsrceenFrame()}{endOffscreenFrame()} pair.
|
\l{QRhi::endOffsrceenFrame()}{endOffscreenFrame()} pair.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class QRhiVulkanRenderPassNativeHandles
|
||||||
|
\internal
|
||||||
|
\inmodule QtGui
|
||||||
|
\brief Holds the Vulkan render pass object backing a QRhiRenderPassDescriptor.
|
||||||
|
*/
|
||||||
|
|
||||||
static inline VkDeviceSize aligned(VkDeviceSize v, VkDeviceSize byteAlign)
|
static inline VkDeviceSize aligned(VkDeviceSize v, VkDeviceSize byteAlign)
|
||||||
{
|
{
|
||||||
return (v + byteAlign - 1) & ~(byteAlign - 1);
|
return (v + byteAlign - 1) & ~(byteAlign - 1);
|
||||||
@ -1469,7 +1498,6 @@ static inline bool checkDeviceLost(VkResult err)
|
|||||||
|
|
||||||
QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags)
|
QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags)
|
||||||
{
|
{
|
||||||
Q_UNUSED(flags);
|
|
||||||
QVkSwapChain *swapChainD = QRHI_RES(QVkSwapChain, swapChain);
|
QVkSwapChain *swapChainD = QRHI_RES(QVkSwapChain, swapChain);
|
||||||
QVkSwapChain::FrameResources &frame(swapChainD->frameRes[swapChainD->currentFrameSlot]);
|
QVkSwapChain::FrameResources &frame(swapChainD->frameRes[swapChainD->currentFrameSlot]);
|
||||||
QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
|
QRhiProfilerPrivate *rhiP = profilerPrivateOrNull();
|
||||||
@ -1518,7 +1546,8 @@ QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::Begin
|
|||||||
if (frame.timestampQueryIndex >= 0) {
|
if (frame.timestampQueryIndex >= 0) {
|
||||||
quint64 timestamp[2] = { 0, 0 };
|
quint64 timestamp[2] = { 0, 0 };
|
||||||
VkResult err = df->vkGetQueryPoolResults(dev, timestampQueryPool, frame.timestampQueryIndex, 2,
|
VkResult err = df->vkGetQueryPoolResults(dev, timestampQueryPool, frame.timestampQueryIndex, 2,
|
||||||
2 * sizeof(quint64), timestamp, sizeof(quint64), VK_QUERY_RESULT_64_BIT);
|
2 * sizeof(quint64), timestamp, sizeof(quint64),
|
||||||
|
VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
|
||||||
timestampQueryPoolMap.clearBit(frame.timestampQueryIndex / 2);
|
timestampQueryPoolMap.clearBit(frame.timestampQueryIndex / 2);
|
||||||
frame.timestampQueryIndex = -1;
|
frame.timestampQueryIndex = -1;
|
||||||
if (err == VK_SUCCESS) {
|
if (err == VK_SUCCESS) {
|
||||||
@ -1540,7 +1569,7 @@ QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::Begin
|
|||||||
}
|
}
|
||||||
|
|
||||||
// build new draw command buffer
|
// build new draw command buffer
|
||||||
QRhi::FrameOpResult cbres = startCommandBuffer(&frame.cmdBuf);
|
QRhi::FrameOpResult cbres = startPrimaryCommandBuffer(&frame.cmdBuf);
|
||||||
if (cbres != QRhi::FrameOpSuccess)
|
if (cbres != QRhi::FrameOpSuccess)
|
||||||
return cbres;
|
return cbres;
|
||||||
|
|
||||||
@ -1564,6 +1593,8 @@ QRhi::FrameOpResult QRhiVulkan::beginFrame(QRhiSwapChain *swapChain, QRhi::Begin
|
|||||||
}
|
}
|
||||||
|
|
||||||
swapChainD->cbWrapper.cb = frame.cmdBuf;
|
swapChainD->cbWrapper.cb = frame.cmdBuf;
|
||||||
|
swapChainD->cbWrapper.useSecondaryCb = flags.testFlag(QRhi::ExternalContentsInPass);
|
||||||
|
|
||||||
QVkSwapChain::ImageResources &image(swapChainD->imageRes[swapChainD->currentImageIndex]);
|
QVkSwapChain::ImageResources &image(swapChainD->imageRes[swapChainD->currentImageIndex]);
|
||||||
swapChainD->rtWrapper.d.fb = image.fb;
|
swapChainD->rtWrapper.d.fb = image.fb;
|
||||||
|
|
||||||
@ -1584,7 +1615,7 @@ QRhi::FrameOpResult QRhiVulkan::endFrame(QRhiSwapChain *swapChain, QRhi::EndFram
|
|||||||
QVkSwapChain *swapChainD = QRHI_RES(QVkSwapChain, swapChain);
|
QVkSwapChain *swapChainD = QRHI_RES(QVkSwapChain, swapChain);
|
||||||
Q_ASSERT(currentSwapChain == swapChainD);
|
Q_ASSERT(currentSwapChain == swapChainD);
|
||||||
|
|
||||||
recordCommandBuffer(&swapChainD->cbWrapper);
|
recordPrimaryCommandBuffer(&swapChainD->cbWrapper);
|
||||||
|
|
||||||
QVkSwapChain::FrameResources &frame(swapChainD->frameRes[swapChainD->currentFrameSlot]);
|
QVkSwapChain::FrameResources &frame(swapChainD->frameRes[swapChainD->currentFrameSlot]);
|
||||||
QVkSwapChain::ImageResources &image(swapChainD->imageRes[swapChainD->currentImageIndex]);
|
QVkSwapChain::ImageResources &image(swapChainD->imageRes[swapChainD->currentImageIndex]);
|
||||||
@ -1628,10 +1659,10 @@ QRhi::FrameOpResult QRhiVulkan::endFrame(QRhiSwapChain *swapChain, QRhi::EndFram
|
|||||||
// stop recording and submit to the queue
|
// stop recording and submit to the queue
|
||||||
Q_ASSERT(!frame.cmdFenceWaitable);
|
Q_ASSERT(!frame.cmdFenceWaitable);
|
||||||
const bool needsPresent = !flags.testFlag(QRhi::SkipPresent);
|
const bool needsPresent = !flags.testFlag(QRhi::SkipPresent);
|
||||||
QRhi::FrameOpResult submitres = endAndSubmitCommandBuffer(frame.cmdBuf,
|
QRhi::FrameOpResult submitres = endAndSubmitPrimaryCommandBuffer(frame.cmdBuf,
|
||||||
frame.cmdFence,
|
frame.cmdFence,
|
||||||
frame.imageSemWaitable ? &frame.imageSem : nullptr,
|
frame.imageSemWaitable ? &frame.imageSem : nullptr,
|
||||||
needsPresent ? &frame.drawSem : nullptr);
|
needsPresent ? &frame.drawSem : nullptr);
|
||||||
if (submitres != QRhi::FrameOpSuccess)
|
if (submitres != QRhi::FrameOpSuccess)
|
||||||
return submitres;
|
return submitres;
|
||||||
|
|
||||||
@ -1702,7 +1733,7 @@ void QRhiVulkan::prepareNewFrame(QRhiCommandBuffer *cb)
|
|||||||
finishActiveReadbacks(); // last, in case the readback-completed callback issues rhi calls
|
finishActiveReadbacks(); // last, in case the readback-completed callback issues rhi calls
|
||||||
}
|
}
|
||||||
|
|
||||||
QRhi::FrameOpResult QRhiVulkan::startCommandBuffer(VkCommandBuffer *cb)
|
QRhi::FrameOpResult QRhiVulkan::startPrimaryCommandBuffer(VkCommandBuffer *cb)
|
||||||
{
|
{
|
||||||
if (*cb) {
|
if (*cb) {
|
||||||
df->vkFreeCommandBuffers(dev, cmdPool, 1, cb);
|
df->vkFreeCommandBuffers(dev, cmdPool, 1, cb);
|
||||||
@ -1741,8 +1772,8 @@ QRhi::FrameOpResult QRhiVulkan::startCommandBuffer(VkCommandBuffer *cb)
|
|||||||
return QRhi::FrameOpSuccess;
|
return QRhi::FrameOpSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRhi::FrameOpResult QRhiVulkan::endAndSubmitCommandBuffer(VkCommandBuffer cb, VkFence cmdFence,
|
QRhi::FrameOpResult QRhiVulkan::endAndSubmitPrimaryCommandBuffer(VkCommandBuffer cb, VkFence cmdFence,
|
||||||
VkSemaphore *waitSem, VkSemaphore *signalSem)
|
VkSemaphore *waitSem, VkSemaphore *signalSem)
|
||||||
{
|
{
|
||||||
VkResult err = df->vkEndCommandBuffer(cb);
|
VkResult err = df->vkEndCommandBuffer(cb);
|
||||||
if (err != VK_SUCCESS) {
|
if (err != VK_SUCCESS) {
|
||||||
@ -1793,9 +1824,9 @@ void QRhiVulkan::waitCommandCompletion(int frameSlot)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QRhi::FrameOpResult QRhiVulkan::beginOffscreenFrame(QRhiCommandBuffer **cb)
|
QRhi::FrameOpResult QRhiVulkan::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags)
|
||||||
{
|
{
|
||||||
QRhi::FrameOpResult cbres = startCommandBuffer(&ofr.cbWrapper.cb);
|
QRhi::FrameOpResult cbres = startPrimaryCommandBuffer(&ofr.cbWrapper.cb);
|
||||||
if (cbres != QRhi::FrameOpSuccess)
|
if (cbres != QRhi::FrameOpSuccess)
|
||||||
return cbres;
|
return cbres;
|
||||||
|
|
||||||
@ -1812,6 +1843,8 @@ QRhi::FrameOpResult QRhiVulkan::beginOffscreenFrame(QRhiCommandBuffer **cb)
|
|||||||
if (swapchains.count() > 1)
|
if (swapchains.count() > 1)
|
||||||
waitCommandCompletion(currentFrameSlot);
|
waitCommandCompletion(currentFrameSlot);
|
||||||
|
|
||||||
|
ofr.cbWrapper.useSecondaryCb = flags.testFlag(QRhi::ExternalContentsInPass);
|
||||||
|
|
||||||
prepareNewFrame(&ofr.cbWrapper);
|
prepareNewFrame(&ofr.cbWrapper);
|
||||||
ofr.active = true;
|
ofr.active = true;
|
||||||
|
|
||||||
@ -1819,12 +1852,13 @@ QRhi::FrameOpResult QRhiVulkan::beginOffscreenFrame(QRhiCommandBuffer **cb)
|
|||||||
return QRhi::FrameOpSuccess;
|
return QRhi::FrameOpSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRhi::FrameOpResult QRhiVulkan::endOffscreenFrame()
|
QRhi::FrameOpResult QRhiVulkan::endOffscreenFrame(QRhi::EndFrameFlags flags)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(flags);
|
||||||
Q_ASSERT(ofr.active);
|
Q_ASSERT(ofr.active);
|
||||||
ofr.active = false;
|
ofr.active = false;
|
||||||
|
|
||||||
recordCommandBuffer(&ofr.cbWrapper);
|
recordPrimaryCommandBuffer(&ofr.cbWrapper);
|
||||||
|
|
||||||
if (!ofr.cmdFence) {
|
if (!ofr.cmdFence) {
|
||||||
VkFenceCreateInfo fenceInfo;
|
VkFenceCreateInfo fenceInfo;
|
||||||
@ -1837,7 +1871,7 @@ QRhi::FrameOpResult QRhiVulkan::endOffscreenFrame()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QRhi::FrameOpResult submitres = endAndSubmitCommandBuffer(ofr.cbWrapper.cb, ofr.cmdFence, nullptr, nullptr);
|
QRhi::FrameOpResult submitres = endAndSubmitPrimaryCommandBuffer(ofr.cbWrapper.cb, ofr.cmdFence, nullptr, nullptr);
|
||||||
if (submitres != QRhi::FrameOpSuccess)
|
if (submitres != QRhi::FrameOpSuccess)
|
||||||
return submitres;
|
return submitres;
|
||||||
|
|
||||||
@ -1861,15 +1895,19 @@ QRhi::FrameOpResult QRhiVulkan::finish()
|
|||||||
VkCommandBuffer cb;
|
VkCommandBuffer cb;
|
||||||
if (ofr.active) {
|
if (ofr.active) {
|
||||||
Q_ASSERT(!currentSwapChain);
|
Q_ASSERT(!currentSwapChain);
|
||||||
recordCommandBuffer(&ofr.cbWrapper);
|
Q_ASSERT(ofr.cbWrapper.recordingPass == QVkCommandBuffer::NoPass);
|
||||||
|
recordPrimaryCommandBuffer(&ofr.cbWrapper);
|
||||||
|
ofr.cbWrapper.resetCommands();
|
||||||
cb = ofr.cbWrapper.cb;
|
cb = ofr.cbWrapper.cb;
|
||||||
} else {
|
} else {
|
||||||
Q_ASSERT(currentSwapChain);
|
Q_ASSERT(currentSwapChain);
|
||||||
|
Q_ASSERT(currentSwapChain->cbWrapper.recordingPass == QVkCommandBuffer::NoPass);
|
||||||
swapChainD = currentSwapChain;
|
swapChainD = currentSwapChain;
|
||||||
recordCommandBuffer(&swapChainD->cbWrapper);
|
recordPrimaryCommandBuffer(&swapChainD->cbWrapper);
|
||||||
|
swapChainD->cbWrapper.resetCommands();
|
||||||
cb = swapChainD->cbWrapper.cb;
|
cb = swapChainD->cbWrapper.cb;
|
||||||
}
|
}
|
||||||
QRhi::FrameOpResult submitres = endAndSubmitCommandBuffer(cb, VK_NULL_HANDLE, nullptr, nullptr);
|
QRhi::FrameOpResult submitres = endAndSubmitPrimaryCommandBuffer(cb, VK_NULL_HANDLE, nullptr, nullptr);
|
||||||
if (submitres != QRhi::FrameOpSuccess)
|
if (submitres != QRhi::FrameOpSuccess)
|
||||||
return submitres;
|
return submitres;
|
||||||
}
|
}
|
||||||
@ -1879,9 +1917,9 @@ QRhi::FrameOpResult QRhiVulkan::finish()
|
|||||||
if (inFrame) {
|
if (inFrame) {
|
||||||
// Allocate and begin recording on a new command buffer.
|
// Allocate and begin recording on a new command buffer.
|
||||||
if (ofr.active)
|
if (ofr.active)
|
||||||
startCommandBuffer(&ofr.cbWrapper.cb);
|
startPrimaryCommandBuffer(&ofr.cbWrapper.cb);
|
||||||
else
|
else
|
||||||
startCommandBuffer(&swapChainD->frameRes[swapChainD->currentFrameSlot].cmdBuf);
|
startPrimaryCommandBuffer(&swapChainD->frameRes[swapChainD->currentFrameSlot].cmdBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
executeDeferredReleases(true);
|
executeDeferredReleases(true);
|
||||||
@ -1955,6 +1993,69 @@ void QRhiVulkan::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *
|
|||||||
enqueueResourceUpdates(cbD, resourceUpdates);
|
enqueueResourceUpdates(cbD, resourceUpdates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkCommandBuffer QRhiVulkan::startSecondaryCommandBuffer(QVkRenderTargetData *rtD)
|
||||||
|
{
|
||||||
|
VkCommandBuffer secondaryCb;
|
||||||
|
|
||||||
|
VkCommandBufferAllocateInfo cmdBufInfo;
|
||||||
|
memset(&cmdBufInfo, 0, sizeof(cmdBufInfo));
|
||||||
|
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||||
|
cmdBufInfo.commandPool = cmdPool;
|
||||||
|
cmdBufInfo.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
|
||||||
|
cmdBufInfo.commandBufferCount = 1;
|
||||||
|
VkResult err = df->vkAllocateCommandBuffers(dev, &cmdBufInfo, &secondaryCb);
|
||||||
|
if (err != VK_SUCCESS) {
|
||||||
|
qWarning("Failed to create secondary command buffer: %d", err);
|
||||||
|
return VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkCommandBufferBeginInfo cmdBufBeginInfo;
|
||||||
|
memset(&cmdBufBeginInfo, 0, sizeof(cmdBufBeginInfo));
|
||||||
|
cmdBufBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
|
cmdBufBeginInfo.flags = rtD ? VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT : 0;
|
||||||
|
VkCommandBufferInheritanceInfo cmdBufInheritInfo;
|
||||||
|
memset(&cmdBufInheritInfo, 0, sizeof(cmdBufInheritInfo));
|
||||||
|
cmdBufInheritInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
|
||||||
|
cmdBufInheritInfo.subpass = 0;
|
||||||
|
if (rtD) {
|
||||||
|
cmdBufInheritInfo.renderPass = rtD->rp->rp;
|
||||||
|
cmdBufInheritInfo.framebuffer = rtD->fb;
|
||||||
|
}
|
||||||
|
cmdBufBeginInfo.pInheritanceInfo = &cmdBufInheritInfo;
|
||||||
|
|
||||||
|
err = df->vkBeginCommandBuffer(secondaryCb, &cmdBufBeginInfo);
|
||||||
|
if (err != VK_SUCCESS) {
|
||||||
|
qWarning("Failed to begin secondary command buffer: %d", err);
|
||||||
|
df->vkFreeCommandBuffers(dev, cmdPool, 1, &secondaryCb);
|
||||||
|
return VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return secondaryCb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QRhiVulkan::endAndEnqueueSecondaryCommandBuffer(VkCommandBuffer cb, QVkCommandBuffer *cbD)
|
||||||
|
{
|
||||||
|
VkResult err = df->vkEndCommandBuffer(cb);
|
||||||
|
if (err != VK_SUCCESS)
|
||||||
|
qWarning("Failed to end secondary command buffer: %d", err);
|
||||||
|
|
||||||
|
QVkCommandBuffer::Command cmd;
|
||||||
|
cmd.cmd = QVkCommandBuffer::Command::ExecuteSecondary;
|
||||||
|
cmd.args.executeSecondary.cb = cb;
|
||||||
|
cbD->commands.append(cmd);
|
||||||
|
|
||||||
|
deferredReleaseSecondaryCommandBuffer(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QRhiVulkan::deferredReleaseSecondaryCommandBuffer(VkCommandBuffer cb)
|
||||||
|
{
|
||||||
|
QRhiVulkan::DeferredReleaseEntry e;
|
||||||
|
e.type = QRhiVulkan::DeferredReleaseEntry::CommandBuffer;
|
||||||
|
e.lastActiveFrameSlot = currentFrameSlot;
|
||||||
|
e.commandBuffer.cb = cb;
|
||||||
|
releaseQueue.append(e);
|
||||||
|
}
|
||||||
|
|
||||||
void QRhiVulkan::beginPass(QRhiCommandBuffer *cb,
|
void QRhiVulkan::beginPass(QRhiCommandBuffer *cb,
|
||||||
QRhiRenderTarget *rt,
|
QRhiRenderTarget *rt,
|
||||||
const QColor &colorClearValue,
|
const QColor &colorClearValue,
|
||||||
@ -2034,6 +2135,9 @@ void QRhiVulkan::beginPass(QRhiCommandBuffer *cb,
|
|||||||
cmd.args.beginRenderPass.clearValueIndex = cbD->pools.clearValue.count();
|
cmd.args.beginRenderPass.clearValueIndex = cbD->pools.clearValue.count();
|
||||||
cbD->pools.clearValue.append(cvs.constData(), cvs.count());
|
cbD->pools.clearValue.append(cvs.constData(), cvs.count());
|
||||||
cbD->commands.append(cmd);
|
cbD->commands.append(cmd);
|
||||||
|
|
||||||
|
if (cbD->useSecondaryCb)
|
||||||
|
cbD->secondaryCbs.append(startSecondaryCommandBuffer(rtD));
|
||||||
}
|
}
|
||||||
|
|
||||||
void QRhiVulkan::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
|
void QRhiVulkan::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
|
||||||
@ -2041,6 +2145,13 @@ void QRhiVulkan::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourc
|
|||||||
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
||||||
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass);
|
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass);
|
||||||
|
|
||||||
|
if (cbD->useSecondaryCb) {
|
||||||
|
VkCommandBuffer secondaryCb = cbD->secondaryCbs.last();
|
||||||
|
cbD->secondaryCbs.removeLast();
|
||||||
|
endAndEnqueueSecondaryCommandBuffer(secondaryCb, cbD);
|
||||||
|
cbD->resetCachedState();
|
||||||
|
}
|
||||||
|
|
||||||
QVkCommandBuffer::Command cmd;
|
QVkCommandBuffer::Command cmd;
|
||||||
cmd.cmd = QVkCommandBuffer::Command::EndRenderPass;
|
cmd.cmd = QVkCommandBuffer::Command::EndRenderPass;
|
||||||
cbD->commands.append(cmd);
|
cbD->commands.append(cmd);
|
||||||
@ -2063,6 +2174,9 @@ void QRhiVulkan::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch
|
|||||||
enqueueTransitionPassResources(cbD);
|
enqueueTransitionPassResources(cbD);
|
||||||
|
|
||||||
cbD->recordingPass = QVkCommandBuffer::ComputePass;
|
cbD->recordingPass = QVkCommandBuffer::ComputePass;
|
||||||
|
|
||||||
|
if (cbD->useSecondaryCb)
|
||||||
|
cbD->secondaryCbs.append(startSecondaryCommandBuffer());
|
||||||
}
|
}
|
||||||
|
|
||||||
void QRhiVulkan::endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
|
void QRhiVulkan::endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
|
||||||
@ -2070,6 +2184,13 @@ void QRhiVulkan::endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *
|
|||||||
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
||||||
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::ComputePass);
|
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::ComputePass);
|
||||||
|
|
||||||
|
if (cbD->useSecondaryCb) {
|
||||||
|
VkCommandBuffer secondaryCb = cbD->secondaryCbs.last();
|
||||||
|
cbD->secondaryCbs.removeLast();
|
||||||
|
endAndEnqueueSecondaryCommandBuffer(secondaryCb, cbD);
|
||||||
|
cbD->resetCachedState();
|
||||||
|
}
|
||||||
|
|
||||||
cbD->recordingPass = QVkCommandBuffer::NoPass;
|
cbD->recordingPass = QVkCommandBuffer::NoPass;
|
||||||
|
|
||||||
if (resourceUpdates)
|
if (resourceUpdates)
|
||||||
@ -2084,11 +2205,15 @@ void QRhiVulkan::setComputePipeline(QRhiCommandBuffer *cb, QRhiComputePipeline *
|
|||||||
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::ComputePass);
|
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::ComputePass);
|
||||||
|
|
||||||
if (cbD->currentComputePipeline != ps || cbD->currentPipelineGeneration != psD->generation) {
|
if (cbD->currentComputePipeline != ps || cbD->currentPipelineGeneration != psD->generation) {
|
||||||
QVkCommandBuffer::Command cmd;
|
if (cbD->useSecondaryCb) {
|
||||||
cmd.cmd = QVkCommandBuffer::Command::BindPipeline;
|
df->vkCmdBindPipeline(cbD->secondaryCbs.last(), VK_PIPELINE_BIND_POINT_COMPUTE, psD->pipeline);
|
||||||
cmd.args.bindPipeline.bindPoint = VK_PIPELINE_BIND_POINT_COMPUTE;
|
} else {
|
||||||
cmd.args.bindPipeline.pipeline = psD->pipeline;
|
QVkCommandBuffer::Command cmd;
|
||||||
cbD->commands.append(cmd);
|
cmd.cmd = QVkCommandBuffer::Command::BindPipeline;
|
||||||
|
cmd.args.bindPipeline.bindPoint = VK_PIPELINE_BIND_POINT_COMPUTE;
|
||||||
|
cmd.args.bindPipeline.pipeline = psD->pipeline;
|
||||||
|
cbD->commands.append(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
cbD->currentGraphicsPipeline = nullptr;
|
cbD->currentGraphicsPipeline = nullptr;
|
||||||
cbD->currentComputePipeline = ps;
|
cbD->currentComputePipeline = ps;
|
||||||
@ -2103,12 +2228,16 @@ void QRhiVulkan::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
|
|||||||
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
||||||
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::ComputePass);
|
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::ComputePass);
|
||||||
|
|
||||||
QVkCommandBuffer::Command cmd;
|
if (cbD->useSecondaryCb) {
|
||||||
cmd.cmd = QVkCommandBuffer::Command::Dispatch;
|
df->vkCmdDispatch(cbD->secondaryCbs.last(), x, y, z);
|
||||||
cmd.args.dispatch.x = x;
|
} else {
|
||||||
cmd.args.dispatch.y = y;
|
QVkCommandBuffer::Command cmd;
|
||||||
cmd.args.dispatch.z = z;
|
cmd.cmd = QVkCommandBuffer::Command::Dispatch;
|
||||||
cbD->commands.append(cmd);
|
cmd.args.dispatch.x = x;
|
||||||
|
cmd.args.dispatch.y = y;
|
||||||
|
cmd.args.dispatch.z = z;
|
||||||
|
cbD->commands.append(cmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VkShaderModule QRhiVulkan::createShader(const QByteArray &spirv)
|
VkShaderModule QRhiVulkan::createShader(const QByteArray &spirv)
|
||||||
@ -3013,6 +3142,9 @@ void QRhiVulkan::executeDeferredReleases(bool forced)
|
|||||||
case QRhiVulkan::DeferredReleaseEntry::StagingBuffer:
|
case QRhiVulkan::DeferredReleaseEntry::StagingBuffer:
|
||||||
vmaDestroyBuffer(toVmaAllocator(allocator), e.stagingBuffer.stagingBuffer, toVmaAllocation(e.stagingBuffer.stagingAllocation));
|
vmaDestroyBuffer(toVmaAllocator(allocator), e.stagingBuffer.stagingBuffer, toVmaAllocation(e.stagingBuffer.stagingAllocation));
|
||||||
break;
|
break;
|
||||||
|
case QRhiVulkan::DeferredReleaseEntry::CommandBuffer:
|
||||||
|
df->vkFreeCommandBuffers(dev, cmdPool, 1, &e.commandBuffer.cb);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Q_UNREACHABLE();
|
Q_UNREACHABLE();
|
||||||
break;
|
break;
|
||||||
@ -3113,14 +3245,15 @@ VkSampleCountFlagBits QRhiVulkan::effectiveSampleCount(int sampleCount)
|
|||||||
void QRhiVulkan::enqueueTransitionPassResources(QVkCommandBuffer *cbD)
|
void QRhiVulkan::enqueueTransitionPassResources(QVkCommandBuffer *cbD)
|
||||||
{
|
{
|
||||||
cbD->passResTrackers.append(QRhiPassResourceTracker());
|
cbD->passResTrackers.append(QRhiPassResourceTracker());
|
||||||
|
cbD->currentPassResTrackerIndex = cbD->passResTrackers.count() - 1;
|
||||||
|
|
||||||
QVkCommandBuffer::Command cmd;
|
QVkCommandBuffer::Command cmd;
|
||||||
cmd.cmd = QVkCommandBuffer::Command::TransitionPassResources;
|
cmd.cmd = QVkCommandBuffer::Command::TransitionPassResources;
|
||||||
cmd.args.transitionResources.trackerIndex = cbD->passResTrackers.count() - 1;
|
cmd.args.transitionResources.trackerIndex = cbD->passResTrackers.count() - 1;
|
||||||
cbD->commands.append(cmd);
|
cbD->commands.append(cmd);
|
||||||
cbD->currentPassResTrackerIndex = cbD->passResTrackers.count() - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QRhiVulkan::recordCommandBuffer(QVkCommandBuffer *cbD)
|
void QRhiVulkan::recordPrimaryCommandBuffer(QVkCommandBuffer *cbD)
|
||||||
{
|
{
|
||||||
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::NoPass);
|
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::NoPass);
|
||||||
|
|
||||||
@ -3165,7 +3298,8 @@ void QRhiVulkan::recordCommandBuffer(QVkCommandBuffer *cbD)
|
|||||||
break;
|
break;
|
||||||
case QVkCommandBuffer::Command::BeginRenderPass:
|
case QVkCommandBuffer::Command::BeginRenderPass:
|
||||||
cmd.args.beginRenderPass.desc.pClearValues = cbD->pools.clearValue.constData() + cmd.args.beginRenderPass.clearValueIndex;
|
cmd.args.beginRenderPass.desc.pClearValues = cbD->pools.clearValue.constData() + cmd.args.beginRenderPass.clearValueIndex;
|
||||||
df->vkCmdBeginRenderPass(cbD->cb, &cmd.args.beginRenderPass.desc, VK_SUBPASS_CONTENTS_INLINE);
|
df->vkCmdBeginRenderPass(cbD->cb, &cmd.args.beginRenderPass.desc,
|
||||||
|
cbD->useSecondaryCb ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : VK_SUBPASS_CONTENTS_INLINE);
|
||||||
break;
|
break;
|
||||||
case QVkCommandBuffer::Command::EndRenderPass:
|
case QVkCommandBuffer::Command::EndRenderPass:
|
||||||
df->vkCmdEndRenderPass(cbD->cb);
|
df->vkCmdEndRenderPass(cbD->cb);
|
||||||
@ -3218,13 +3352,15 @@ void QRhiVulkan::recordCommandBuffer(QVkCommandBuffer *cbD)
|
|||||||
break;
|
break;
|
||||||
case QVkCommandBuffer::Command::DebugMarkerBegin:
|
case QVkCommandBuffer::Command::DebugMarkerBegin:
|
||||||
cmd.args.debugMarkerBegin.marker.pMarkerName =
|
cmd.args.debugMarkerBegin.marker.pMarkerName =
|
||||||
cbD->pools.debugMarkerName[cmd.args.debugMarkerBegin.markerNameIndex].constData();
|
cbD->pools.debugMarkerData[cmd.args.debugMarkerBegin.markerNameIndex].constData();
|
||||||
vkCmdDebugMarkerBegin(cbD->cb, &cmd.args.debugMarkerBegin.marker);
|
vkCmdDebugMarkerBegin(cbD->cb, &cmd.args.debugMarkerBegin.marker);
|
||||||
break;
|
break;
|
||||||
case QVkCommandBuffer::Command::DebugMarkerEnd:
|
case QVkCommandBuffer::Command::DebugMarkerEnd:
|
||||||
vkCmdDebugMarkerEnd(cbD->cb);
|
vkCmdDebugMarkerEnd(cbD->cb);
|
||||||
break;
|
break;
|
||||||
case QVkCommandBuffer::Command::DebugMarkerInsert:
|
case QVkCommandBuffer::Command::DebugMarkerInsert:
|
||||||
|
cmd.args.debugMarkerInsert.marker.pMarkerName =
|
||||||
|
cbD->pools.debugMarkerData[cmd.args.debugMarkerInsert.markerNameIndex].constData();
|
||||||
vkCmdDebugMarkerInsert(cbD->cb, &cmd.args.debugMarkerInsert.marker);
|
vkCmdDebugMarkerInsert(cbD->cb, &cmd.args.debugMarkerInsert.marker);
|
||||||
break;
|
break;
|
||||||
case QVkCommandBuffer::Command::TransitionPassResources:
|
case QVkCommandBuffer::Command::TransitionPassResources:
|
||||||
@ -3233,12 +3369,13 @@ void QRhiVulkan::recordCommandBuffer(QVkCommandBuffer *cbD)
|
|||||||
case QVkCommandBuffer::Command::Dispatch:
|
case QVkCommandBuffer::Command::Dispatch:
|
||||||
df->vkCmdDispatch(cbD->cb, cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
|
df->vkCmdDispatch(cbD->cb, cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
|
||||||
break;
|
break;
|
||||||
|
case QVkCommandBuffer::Command::ExecuteSecondary:
|
||||||
|
df->vkCmdExecuteCommands(cbD->cb, 1, &cmd.args.executeSecondary.cb);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cbD->resetCommands();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline VkAccessFlags toVkAccess(QRhiPassResourceTracker::BufferAccess access)
|
static inline VkAccessFlags toVkAccess(QRhiPassResourceTracker::BufferAccess access)
|
||||||
@ -3655,11 +3792,15 @@ void QRhiVulkan::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
|
|||||||
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass);
|
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass);
|
||||||
|
|
||||||
if (cbD->currentGraphicsPipeline != ps || cbD->currentPipelineGeneration != psD->generation) {
|
if (cbD->currentGraphicsPipeline != ps || cbD->currentPipelineGeneration != psD->generation) {
|
||||||
QVkCommandBuffer::Command cmd;
|
if (cbD->useSecondaryCb) {
|
||||||
cmd.cmd = QVkCommandBuffer::Command::BindPipeline;
|
df->vkCmdBindPipeline(cbD->secondaryCbs.last(), VK_PIPELINE_BIND_POINT_GRAPHICS, psD->pipeline);
|
||||||
cmd.args.bindPipeline.bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
} else {
|
||||||
cmd.args.bindPipeline.pipeline = psD->pipeline;
|
QVkCommandBuffer::Command cmd;
|
||||||
cbD->commands.append(cmd);
|
cmd.cmd = QVkCommandBuffer::Command::BindPipeline;
|
||||||
|
cmd.args.bindPipeline.bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||||
|
cmd.args.bindPipeline.pipeline = psD->pipeline;
|
||||||
|
cbD->commands.append(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
cbD->currentGraphicsPipeline = ps;
|
cbD->currentGraphicsPipeline = ps;
|
||||||
cbD->currentComputePipeline = nullptr;
|
cbD->currentComputePipeline = nullptr;
|
||||||
@ -3857,16 +3998,25 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QVkCommandBuffer::Command cmd;
|
if (cbD->useSecondaryCb) {
|
||||||
cmd.cmd = QVkCommandBuffer::Command::BindDescriptorSet;
|
df->vkCmdBindDescriptorSets(cbD->secondaryCbs.last(),
|
||||||
cmd.args.bindDescriptorSet.bindPoint = gfxPsD ? VK_PIPELINE_BIND_POINT_GRAPHICS
|
gfxPsD ? VK_PIPELINE_BIND_POINT_GRAPHICS : VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||||
: VK_PIPELINE_BIND_POINT_COMPUTE;
|
gfxPsD ? gfxPsD->layout : compPsD->layout,
|
||||||
cmd.args.bindDescriptorSet.pipelineLayout = gfxPsD ? gfxPsD->layout : compPsD->layout;
|
0, 1, &srbD->descSets[descSetIdx],
|
||||||
cmd.args.bindDescriptorSet.descSet = srbD->descSets[descSetIdx];
|
dynOfs.count(),
|
||||||
cmd.args.bindDescriptorSet.dynamicOffsetCount = dynOfs.count();
|
dynOfs.count() ? dynOfs.constData() : nullptr);
|
||||||
cmd.args.bindDescriptorSet.dynamicOffsetIndex = cbD->pools.dynamicOffset.count();
|
} else {
|
||||||
cbD->pools.dynamicOffset.append(dynOfs.constData(), dynOfs.count());
|
QVkCommandBuffer::Command cmd;
|
||||||
cbD->commands.append(cmd);
|
cmd.cmd = QVkCommandBuffer::Command::BindDescriptorSet;
|
||||||
|
cmd.args.bindDescriptorSet.bindPoint = gfxPsD ? VK_PIPELINE_BIND_POINT_GRAPHICS
|
||||||
|
: VK_PIPELINE_BIND_POINT_COMPUTE;
|
||||||
|
cmd.args.bindDescriptorSet.pipelineLayout = gfxPsD ? gfxPsD->layout : compPsD->layout;
|
||||||
|
cmd.args.bindDescriptorSet.descSet = srbD->descSets[descSetIdx];
|
||||||
|
cmd.args.bindDescriptorSet.dynamicOffsetCount = dynOfs.count();
|
||||||
|
cmd.args.bindDescriptorSet.dynamicOffsetIndex = cbD->pools.dynamicOffset.count();
|
||||||
|
cbD->pools.dynamicOffset.append(dynOfs.constData(), dynOfs.count());
|
||||||
|
cbD->commands.append(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
if (gfxPsD) {
|
if (gfxPsD) {
|
||||||
cbD->currentGraphicsSrb = srb;
|
cbD->currentGraphicsSrb = srb;
|
||||||
@ -3922,15 +4072,20 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb,
|
|||||||
QRhiPassResourceTracker::BufVertexInputStage);
|
QRhiPassResourceTracker::BufVertexInputStage);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVkCommandBuffer::Command cmd;
|
if (cbD->useSecondaryCb) {
|
||||||
cmd.cmd = QVkCommandBuffer::Command::BindVertexBuffer;
|
df->vkCmdBindVertexBuffers(cbD->secondaryCbs.last(), startBinding,
|
||||||
cmd.args.bindVertexBuffer.startBinding = startBinding;
|
bufs.count(), bufs.constData(), ofs.constData());
|
||||||
cmd.args.bindVertexBuffer.count = bufs.count();
|
} else {
|
||||||
cmd.args.bindVertexBuffer.vertexBufferIndex = cbD->pools.vertexBuffer.count();
|
QVkCommandBuffer::Command cmd;
|
||||||
cbD->pools.vertexBuffer.append(bufs.constData(), bufs.count());
|
cmd.cmd = QVkCommandBuffer::Command::BindVertexBuffer;
|
||||||
cmd.args.bindVertexBuffer.vertexBufferOffsetIndex = cbD->pools.vertexBufferOffset.count();
|
cmd.args.bindVertexBuffer.startBinding = startBinding;
|
||||||
cbD->pools.vertexBufferOffset.append(ofs.constData(), ofs.count());
|
cmd.args.bindVertexBuffer.count = bufs.count();
|
||||||
cbD->commands.append(cmd);
|
cmd.args.bindVertexBuffer.vertexBufferIndex = cbD->pools.vertexBuffer.count();
|
||||||
|
cbD->pools.vertexBuffer.append(bufs.constData(), bufs.count());
|
||||||
|
cmd.args.bindVertexBuffer.vertexBufferOffsetIndex = cbD->pools.vertexBufferOffset.count();
|
||||||
|
cbD->pools.vertexBufferOffset.append(ofs.constData(), ofs.count());
|
||||||
|
cbD->commands.append(cmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (indexBuf) {
|
if (indexBuf) {
|
||||||
@ -3953,12 +4108,16 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb,
|
|||||||
cbD->currentIndexOffset = indexOffset;
|
cbD->currentIndexOffset = indexOffset;
|
||||||
cbD->currentIndexFormat = type;
|
cbD->currentIndexFormat = type;
|
||||||
|
|
||||||
QVkCommandBuffer::Command cmd;
|
if (cbD->useSecondaryCb) {
|
||||||
cmd.cmd = QVkCommandBuffer::Command::BindIndexBuffer;
|
df->vkCmdBindIndexBuffer(cbD->secondaryCbs.last(), vkindexbuf, indexOffset, type);
|
||||||
cmd.args.bindIndexBuffer.buf = vkindexbuf;
|
} else {
|
||||||
cmd.args.bindIndexBuffer.ofs = indexOffset;
|
QVkCommandBuffer::Command cmd;
|
||||||
cmd.args.bindIndexBuffer.type = type;
|
cmd.cmd = QVkCommandBuffer::Command::BindIndexBuffer;
|
||||||
cbD->commands.append(cmd);
|
cmd.args.bindIndexBuffer.buf = vkindexbuf;
|
||||||
|
cmd.args.bindIndexBuffer.ofs = indexOffset;
|
||||||
|
cmd.args.bindIndexBuffer.type = type;
|
||||||
|
cbD->commands.append(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
trackedRegisterBuffer(&passResTracker, ibufD, slot,
|
trackedRegisterBuffer(&passResTracker, ibufD, slot,
|
||||||
QRhiPassResourceTracker::BufIndexRead,
|
QRhiPassResourceTracker::BufIndexRead,
|
||||||
@ -3979,7 +4138,6 @@ void QRhiVulkan::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
QVkCommandBuffer::Command cmd;
|
QVkCommandBuffer::Command cmd;
|
||||||
cmd.cmd = QVkCommandBuffer::Command::SetViewport;
|
|
||||||
VkViewport *vp = &cmd.args.setViewport.viewport;
|
VkViewport *vp = &cmd.args.setViewport.viewport;
|
||||||
vp->x = x;
|
vp->x = x;
|
||||||
vp->y = y;
|
vp->y = y;
|
||||||
@ -3987,16 +4145,26 @@ void QRhiVulkan::setViewport(QRhiCommandBuffer *cb, const QRhiViewport &viewport
|
|||||||
vp->height = h;
|
vp->height = h;
|
||||||
vp->minDepth = viewport.minDepth();
|
vp->minDepth = viewport.minDepth();
|
||||||
vp->maxDepth = viewport.maxDepth();
|
vp->maxDepth = viewport.maxDepth();
|
||||||
cbD->commands.append(cmd);
|
|
||||||
|
if (cbD->useSecondaryCb) {
|
||||||
|
df->vkCmdSetViewport(cbD->secondaryCbs.last(), 0, 1, vp);
|
||||||
|
} else {
|
||||||
|
cmd.cmd = QVkCommandBuffer::Command::SetViewport;
|
||||||
|
cbD->commands.append(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
if (!QRHI_RES(QVkGraphicsPipeline, cbD->currentGraphicsPipeline)->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor)) {
|
if (!QRHI_RES(QVkGraphicsPipeline, cbD->currentGraphicsPipeline)->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor)) {
|
||||||
cmd.cmd = QVkCommandBuffer::Command::SetScissor;
|
|
||||||
VkRect2D *s = &cmd.args.setScissor.scissor;
|
VkRect2D *s = &cmd.args.setScissor.scissor;
|
||||||
s->offset.x = x;
|
s->offset.x = x;
|
||||||
s->offset.y = y;
|
s->offset.y = y;
|
||||||
s->extent.width = w;
|
s->extent.width = w;
|
||||||
s->extent.height = h;
|
s->extent.height = h;
|
||||||
cbD->commands.append(cmd);
|
if (cbD->useSecondaryCb) {
|
||||||
|
df->vkCmdSetScissor(cbD->secondaryCbs.last(), 0, 1, s);
|
||||||
|
} else {
|
||||||
|
cmd.cmd = QVkCommandBuffer::Command::SetScissor;
|
||||||
|
cbD->commands.append(cmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4013,13 +4181,18 @@ void QRhiVulkan::setScissor(QRhiCommandBuffer *cb, const QRhiScissor &scissor)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
QVkCommandBuffer::Command cmd;
|
QVkCommandBuffer::Command cmd;
|
||||||
cmd.cmd = QVkCommandBuffer::Command::SetScissor;
|
|
||||||
VkRect2D *s = &cmd.args.setScissor.scissor;
|
VkRect2D *s = &cmd.args.setScissor.scissor;
|
||||||
s->offset.x = x;
|
s->offset.x = x;
|
||||||
s->offset.y = y;
|
s->offset.y = y;
|
||||||
s->extent.width = w;
|
s->extent.width = w;
|
||||||
s->extent.height = h;
|
s->extent.height = h;
|
||||||
cbD->commands.append(cmd);
|
|
||||||
|
if (cbD->useSecondaryCb) {
|
||||||
|
df->vkCmdSetScissor(cbD->secondaryCbs.last(), 0, 1, s);
|
||||||
|
} else {
|
||||||
|
cmd.cmd = QVkCommandBuffer::Command::SetScissor;
|
||||||
|
cbD->commands.append(cmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QRhiVulkan::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c)
|
void QRhiVulkan::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c)
|
||||||
@ -4027,13 +4200,18 @@ void QRhiVulkan::setBlendConstants(QRhiCommandBuffer *cb, const QColor &c)
|
|||||||
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
||||||
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass);
|
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass);
|
||||||
|
|
||||||
QVkCommandBuffer::Command cmd;
|
if (cbD->useSecondaryCb) {
|
||||||
cmd.cmd = QVkCommandBuffer::Command::SetBlendConstants;
|
float constants[] = { float(c.redF()), float(c.greenF()), float(c.blueF()), float(c.alphaF()) };
|
||||||
cmd.args.setBlendConstants.c[0] = c.redF();
|
df->vkCmdSetBlendConstants(cbD->secondaryCbs.last(), constants);
|
||||||
cmd.args.setBlendConstants.c[1] = c.greenF();
|
} else {
|
||||||
cmd.args.setBlendConstants.c[2] = c.blueF();
|
QVkCommandBuffer::Command cmd;
|
||||||
cmd.args.setBlendConstants.c[3] = c.alphaF();
|
cmd.cmd = QVkCommandBuffer::Command::SetBlendConstants;
|
||||||
cbD->commands.append(cmd);
|
cmd.args.setBlendConstants.c[0] = c.redF();
|
||||||
|
cmd.args.setBlendConstants.c[1] = c.greenF();
|
||||||
|
cmd.args.setBlendConstants.c[2] = c.blueF();
|
||||||
|
cmd.args.setBlendConstants.c[3] = c.alphaF();
|
||||||
|
cbD->commands.append(cmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QRhiVulkan::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue)
|
void QRhiVulkan::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue)
|
||||||
@ -4041,10 +4219,14 @@ void QRhiVulkan::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue)
|
|||||||
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
||||||
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass);
|
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass);
|
||||||
|
|
||||||
QVkCommandBuffer::Command cmd;
|
if (cbD->useSecondaryCb) {
|
||||||
cmd.cmd = QVkCommandBuffer::Command::SetStencilRef;
|
df->vkCmdSetStencilReference(cbD->secondaryCbs.last(), VK_STENCIL_FRONT_AND_BACK, refValue);
|
||||||
cmd.args.setStencilRef.ref = refValue;
|
} else {
|
||||||
cbD->commands.append(cmd);
|
QVkCommandBuffer::Command cmd;
|
||||||
|
cmd.cmd = QVkCommandBuffer::Command::SetStencilRef;
|
||||||
|
cmd.args.setStencilRef.ref = refValue;
|
||||||
|
cbD->commands.append(cmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QRhiVulkan::draw(QRhiCommandBuffer *cb, quint32 vertexCount,
|
void QRhiVulkan::draw(QRhiCommandBuffer *cb, quint32 vertexCount,
|
||||||
@ -4053,13 +4235,17 @@ void QRhiVulkan::draw(QRhiCommandBuffer *cb, quint32 vertexCount,
|
|||||||
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
||||||
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass);
|
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass);
|
||||||
|
|
||||||
QVkCommandBuffer::Command cmd;
|
if (cbD->useSecondaryCb) {
|
||||||
cmd.cmd = QVkCommandBuffer::Command::Draw;
|
df->vkCmdDraw(cbD->secondaryCbs.last(), vertexCount, instanceCount, firstVertex, firstInstance);
|
||||||
cmd.args.draw.vertexCount = vertexCount;
|
} else {
|
||||||
cmd.args.draw.instanceCount = instanceCount;
|
QVkCommandBuffer::Command cmd;
|
||||||
cmd.args.draw.firstVertex = firstVertex;
|
cmd.cmd = QVkCommandBuffer::Command::Draw;
|
||||||
cmd.args.draw.firstInstance = firstInstance;
|
cmd.args.draw.vertexCount = vertexCount;
|
||||||
cbD->commands.append(cmd);
|
cmd.args.draw.instanceCount = instanceCount;
|
||||||
|
cmd.args.draw.firstVertex = firstVertex;
|
||||||
|
cmd.args.draw.firstInstance = firstInstance;
|
||||||
|
cbD->commands.append(cmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QRhiVulkan::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
|
void QRhiVulkan::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
|
||||||
@ -4068,14 +4254,19 @@ void QRhiVulkan::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount,
|
|||||||
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
||||||
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass);
|
Q_ASSERT(cbD->recordingPass == QVkCommandBuffer::RenderPass);
|
||||||
|
|
||||||
QVkCommandBuffer::Command cmd;
|
if (cbD->useSecondaryCb) {
|
||||||
cmd.cmd = QVkCommandBuffer::Command::DrawIndexed;
|
df->vkCmdDrawIndexed(cbD->secondaryCbs.last(), indexCount, instanceCount,
|
||||||
cmd.args.drawIndexed.indexCount = indexCount;
|
firstIndex, vertexOffset, firstInstance);
|
||||||
cmd.args.drawIndexed.instanceCount = instanceCount;
|
} else {
|
||||||
cmd.args.drawIndexed.firstIndex = firstIndex;
|
QVkCommandBuffer::Command cmd;
|
||||||
cmd.args.drawIndexed.vertexOffset = vertexOffset;
|
cmd.cmd = QVkCommandBuffer::Command::DrawIndexed;
|
||||||
cmd.args.drawIndexed.firstInstance = firstInstance;
|
cmd.args.drawIndexed.indexCount = indexCount;
|
||||||
cbD->commands.append(cmd);
|
cmd.args.drawIndexed.instanceCount = instanceCount;
|
||||||
|
cmd.args.drawIndexed.firstIndex = firstIndex;
|
||||||
|
cmd.args.drawIndexed.vertexOffset = vertexOffset;
|
||||||
|
cmd.args.drawIndexed.firstInstance = firstInstance;
|
||||||
|
cbD->commands.append(cmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QRhiVulkan::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name)
|
void QRhiVulkan::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name)
|
||||||
@ -4088,12 +4279,17 @@ void QRhiVulkan::debugMarkBegin(QRhiCommandBuffer *cb, const QByteArray &name)
|
|||||||
marker.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
|
marker.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
|
||||||
|
|
||||||
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
||||||
QVkCommandBuffer::Command cmd;
|
if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->useSecondaryCb) {
|
||||||
cmd.cmd = QVkCommandBuffer::Command::DebugMarkerBegin;
|
marker.pMarkerName = name.constData();
|
||||||
cmd.args.debugMarkerBegin.marker = marker;
|
vkCmdDebugMarkerBegin(cbD->secondaryCbs.last(), &marker);
|
||||||
cmd.args.debugMarkerBegin.markerNameIndex = cbD->pools.debugMarkerName.count();
|
} else {
|
||||||
cbD->pools.debugMarkerName.append(name);
|
QVkCommandBuffer::Command cmd;
|
||||||
cbD->commands.append(cmd);
|
cmd.cmd = QVkCommandBuffer::Command::DebugMarkerBegin;
|
||||||
|
cmd.args.debugMarkerBegin.marker = marker;
|
||||||
|
cmd.args.debugMarkerBegin.markerNameIndex = cbD->pools.debugMarkerData.count();
|
||||||
|
cbD->pools.debugMarkerData.append(name);
|
||||||
|
cbD->commands.append(cmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QRhiVulkan::debugMarkEnd(QRhiCommandBuffer *cb)
|
void QRhiVulkan::debugMarkEnd(QRhiCommandBuffer *cb)
|
||||||
@ -4102,9 +4298,13 @@ void QRhiVulkan::debugMarkEnd(QRhiCommandBuffer *cb)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
||||||
QVkCommandBuffer::Command cmd;
|
if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->useSecondaryCb) {
|
||||||
cmd.cmd = QVkCommandBuffer::Command::DebugMarkerEnd;
|
vkCmdDebugMarkerEnd(cbD->secondaryCbs.last());
|
||||||
cbD->commands.append(cmd);
|
} else {
|
||||||
|
QVkCommandBuffer::Command cmd;
|
||||||
|
cmd.cmd = QVkCommandBuffer::Command::DebugMarkerEnd;
|
||||||
|
cbD->commands.append(cmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QRhiVulkan::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg)
|
void QRhiVulkan::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg)
|
||||||
@ -4115,13 +4315,19 @@ void QRhiVulkan::debugMarkMsg(QRhiCommandBuffer *cb, const QByteArray &msg)
|
|||||||
VkDebugMarkerMarkerInfoEXT marker;
|
VkDebugMarkerMarkerInfoEXT marker;
|
||||||
memset(&marker, 0, sizeof(marker));
|
memset(&marker, 0, sizeof(marker));
|
||||||
marker.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
|
marker.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
|
||||||
marker.pMarkerName = msg.constData();
|
|
||||||
|
|
||||||
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
||||||
QVkCommandBuffer::Command cmd;
|
if (cbD->recordingPass != QVkCommandBuffer::NoPass && cbD->useSecondaryCb) {
|
||||||
cmd.cmd = QVkCommandBuffer::Command::DebugMarkerInsert;
|
marker.pMarkerName = msg.constData();
|
||||||
cmd.args.debugMarkerInsert.marker = marker;
|
vkCmdDebugMarkerInsert(cbD->secondaryCbs.last(), &marker);
|
||||||
cbD->commands.append(cmd);
|
} else {
|
||||||
|
QVkCommandBuffer::Command cmd;
|
||||||
|
cmd.cmd = QVkCommandBuffer::Command::DebugMarkerInsert;
|
||||||
|
cmd.args.debugMarkerInsert.marker = marker;
|
||||||
|
cmd.args.debugMarkerInsert.markerNameIndex = cbD->pools.debugMarkerData.count();
|
||||||
|
cbD->pools.debugMarkerData.append(msg);
|
||||||
|
cbD->commands.append(cmd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const QRhiNativeHandles *QRhiVulkan::nativeHandles(QRhiCommandBuffer *cb)
|
const QRhiNativeHandles *QRhiVulkan::nativeHandles(QRhiCommandBuffer *cb)
|
||||||
@ -4129,14 +4335,76 @@ const QRhiNativeHandles *QRhiVulkan::nativeHandles(QRhiCommandBuffer *cb)
|
|||||||
return QRHI_RES(QVkCommandBuffer, cb)->nativeHandles();
|
return QRHI_RES(QVkCommandBuffer, cb)->nativeHandles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline QVkRenderTargetData *maybeRenderTargetData(QVkCommandBuffer *cbD)
|
||||||
|
{
|
||||||
|
Q_ASSERT(cbD->currentTarget);
|
||||||
|
QVkRenderTargetData *rtD = nullptr;
|
||||||
|
if (cbD->recordingPass == QVkCommandBuffer::RenderPass) {
|
||||||
|
switch (cbD->currentTarget->resourceType()) {
|
||||||
|
case QRhiResource::RenderTarget:
|
||||||
|
rtD = &QRHI_RES(QVkReferenceRenderTarget, cbD->currentTarget)->d;
|
||||||
|
break;
|
||||||
|
case QRhiResource::TextureRenderTarget:
|
||||||
|
rtD = &QRHI_RES(QVkTextureRenderTarget, cbD->currentTarget)->d;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rtD;
|
||||||
|
}
|
||||||
|
|
||||||
void QRhiVulkan::beginExternal(QRhiCommandBuffer *cb)
|
void QRhiVulkan::beginExternal(QRhiCommandBuffer *cb)
|
||||||
{
|
{
|
||||||
Q_UNUSED(cb);
|
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
||||||
|
|
||||||
|
// When not in a pass, it is simple: record what we have (but do not
|
||||||
|
// submit), the cb can then be used to record more external commands.
|
||||||
|
if (cbD->recordingPass == QVkCommandBuffer::NoPass) {
|
||||||
|
recordPrimaryCommandBuffer(cbD);
|
||||||
|
cbD->resetCommands();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, inside a pass, have a secondary command buffer (with
|
||||||
|
// RENDER_PASS_CONTINUE). Using the main one is not acceptable since we
|
||||||
|
// cannot just record at this stage, that would mess up the resource
|
||||||
|
// tracking and commands like TransitionPassResources.
|
||||||
|
|
||||||
|
if (cbD->inExternal)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!cbD->useSecondaryCb) {
|
||||||
|
qWarning("beginExternal() within a pass is only supported with secondary command buffers. "
|
||||||
|
"This can be enabled by passing QRhi::ExternalContentsInPass to beginFrame().");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkCommandBuffer secondaryCb = cbD->secondaryCbs.last();
|
||||||
|
cbD->secondaryCbs.removeLast();
|
||||||
|
endAndEnqueueSecondaryCommandBuffer(secondaryCb, cbD);
|
||||||
|
|
||||||
|
VkCommandBuffer extCb = startSecondaryCommandBuffer(maybeRenderTargetData(cbD));
|
||||||
|
if (extCb) {
|
||||||
|
cbD->secondaryCbs.append(extCb);
|
||||||
|
cbD->inExternal = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QRhiVulkan::endExternal(QRhiCommandBuffer *cb)
|
void QRhiVulkan::endExternal(QRhiCommandBuffer *cb)
|
||||||
{
|
{
|
||||||
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
QVkCommandBuffer *cbD = QRHI_RES(QVkCommandBuffer, cb);
|
||||||
|
|
||||||
|
if (cbD->recordingPass == QVkCommandBuffer::NoPass) {
|
||||||
|
Q_ASSERT(cbD->commands.isEmpty() && cbD->currentPassResTrackerIndex == -1);
|
||||||
|
} else if (cbD->inExternal) {
|
||||||
|
VkCommandBuffer extCb = cbD->secondaryCbs.last();
|
||||||
|
cbD->secondaryCbs.removeLast();
|
||||||
|
endAndEnqueueSecondaryCommandBuffer(extCb, cbD);
|
||||||
|
cbD->secondaryCbs.append(startSecondaryCommandBuffer(maybeRenderTargetData(cbD)));
|
||||||
|
}
|
||||||
|
|
||||||
cbD->resetCachedState();
|
cbD->resetCachedState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5098,6 +5366,12 @@ void QVkRenderPassDescriptor::release()
|
|||||||
rhiD->unregisterResource(this);
|
rhiD->unregisterResource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QRhiNativeHandles *QVkRenderPassDescriptor::nativeHandles()
|
||||||
|
{
|
||||||
|
nativeHandlesStruct.renderPass = rp;
|
||||||
|
return &nativeHandlesStruct;
|
||||||
|
}
|
||||||
|
|
||||||
QVkReferenceRenderTarget::QVkReferenceRenderTarget(QRhiImplementation *rhi)
|
QVkReferenceRenderTarget::QVkReferenceRenderTarget(QRhiImplementation *rhi)
|
||||||
: QRhiRenderTarget(rhi)
|
: QRhiRenderTarget(rhi)
|
||||||
{
|
{
|
||||||
@ -5786,6 +6060,22 @@ void QVkCommandBuffer::release()
|
|||||||
// nothing to do here, cb is not owned by us
|
// nothing to do here, cb is not owned by us
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QRhiNativeHandles *QVkCommandBuffer::nativeHandles()
|
||||||
|
{
|
||||||
|
// Ok this is messy but no other way has been devised yet. Outside
|
||||||
|
// begin(Compute)Pass - end(Compute)Pass it is simple - just return the
|
||||||
|
// primary VkCommandBuffer. Inside, however, we need to provide the current
|
||||||
|
// secondary command buffer (typically the one started by beginExternal(),
|
||||||
|
// in case we are between beginExternal - endExternal inside a pass).
|
||||||
|
|
||||||
|
if (useSecondaryCb && !secondaryCbs.isEmpty())
|
||||||
|
nativeHandlesStruct.commandBuffer = secondaryCbs.last();
|
||||||
|
else
|
||||||
|
nativeHandlesStruct.commandBuffer = cb;
|
||||||
|
|
||||||
|
return &nativeHandlesStruct;
|
||||||
|
}
|
||||||
|
|
||||||
QVkSwapChain::QVkSwapChain(QRhiImplementation *rhi)
|
QVkSwapChain::QVkSwapChain(QRhiImplementation *rhi)
|
||||||
: QRhiSwapChain(rhi),
|
: QRhiSwapChain(rhi),
|
||||||
rtWrapper(rhi),
|
rtWrapper(rhi),
|
||||||
|
@ -80,6 +80,11 @@ struct Q_GUI_EXPORT QRhiVulkanCommandBufferNativeHandles : public QRhiNativeHand
|
|||||||
VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
|
VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Q_GUI_EXPORT QRhiVulkanRenderPassNativeHandles : public QRhiNativeHandles
|
||||||
|
{
|
||||||
|
VkRenderPass renderPass = VK_NULL_HANDLE;
|
||||||
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -171,9 +171,11 @@ struct QVkRenderPassDescriptor : public QRhiRenderPassDescriptor
|
|||||||
QVkRenderPassDescriptor(QRhiImplementation *rhi);
|
QVkRenderPassDescriptor(QRhiImplementation *rhi);
|
||||||
~QVkRenderPassDescriptor();
|
~QVkRenderPassDescriptor();
|
||||||
void release() override;
|
void release() override;
|
||||||
|
const QRhiNativeHandles *nativeHandles() override;
|
||||||
|
|
||||||
VkRenderPass rp = VK_NULL_HANDLE;
|
VkRenderPass rp = VK_NULL_HANDLE;
|
||||||
bool ownsRp = false;
|
bool ownsRp = false;
|
||||||
|
QRhiVulkanRenderPassNativeHandles nativeHandlesStruct;
|
||||||
int lastActiveFrameSlot = -1;
|
int lastActiveFrameSlot = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -307,13 +309,11 @@ struct QVkCommandBuffer : public QRhiCommandBuffer
|
|||||||
~QVkCommandBuffer();
|
~QVkCommandBuffer();
|
||||||
void release() override;
|
void release() override;
|
||||||
|
|
||||||
VkCommandBuffer cb = VK_NULL_HANDLE;
|
const QRhiNativeHandles *nativeHandles();
|
||||||
QRhiVulkanCommandBufferNativeHandles nativeHandlesStruct;
|
|
||||||
|
|
||||||
const QRhiNativeHandles *nativeHandles() {
|
VkCommandBuffer cb = VK_NULL_HANDLE; // primary
|
||||||
nativeHandlesStruct.commandBuffer = cb;
|
bool useSecondaryCb = false;
|
||||||
return &nativeHandlesStruct;
|
QRhiVulkanCommandBufferNativeHandles nativeHandlesStruct;
|
||||||
}
|
|
||||||
|
|
||||||
enum PassType {
|
enum PassType {
|
||||||
NoPass,
|
NoPass,
|
||||||
@ -322,9 +322,12 @@ struct QVkCommandBuffer : public QRhiCommandBuffer
|
|||||||
};
|
};
|
||||||
|
|
||||||
void resetState() {
|
void resetState() {
|
||||||
resetCommands();
|
|
||||||
recordingPass = NoPass;
|
recordingPass = NoPass;
|
||||||
currentTarget = nullptr;
|
currentTarget = nullptr;
|
||||||
|
|
||||||
|
secondaryCbs.clear();
|
||||||
|
|
||||||
|
resetCommands();
|
||||||
resetCachedState();
|
resetCachedState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,6 +344,7 @@ struct QVkCommandBuffer : public QRhiCommandBuffer
|
|||||||
currentIndexFormat = VK_INDEX_TYPE_UINT16;
|
currentIndexFormat = VK_INDEX_TYPE_UINT16;
|
||||||
memset(currentVertexBuffers, 0, sizeof(currentVertexBuffers));
|
memset(currentVertexBuffers, 0, sizeof(currentVertexBuffers));
|
||||||
memset(currentVertexOffsets, 0, sizeof(currentVertexOffsets));
|
memset(currentVertexOffsets, 0, sizeof(currentVertexOffsets));
|
||||||
|
inExternal = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PassType recordingPass;
|
PassType recordingPass;
|
||||||
@ -358,6 +362,8 @@ struct QVkCommandBuffer : public QRhiCommandBuffer
|
|||||||
static const int VERTEX_INPUT_RESOURCE_SLOT_COUNT = 32;
|
static const int VERTEX_INPUT_RESOURCE_SLOT_COUNT = 32;
|
||||||
VkBuffer currentVertexBuffers[VERTEX_INPUT_RESOURCE_SLOT_COUNT];
|
VkBuffer currentVertexBuffers[VERTEX_INPUT_RESOURCE_SLOT_COUNT];
|
||||||
quint32 currentVertexOffsets[VERTEX_INPUT_RESOURCE_SLOT_COUNT];
|
quint32 currentVertexOffsets[VERTEX_INPUT_RESOURCE_SLOT_COUNT];
|
||||||
|
QVarLengthArray<VkCommandBuffer, 4> secondaryCbs;
|
||||||
|
bool inExternal;
|
||||||
|
|
||||||
struct Command {
|
struct Command {
|
||||||
enum Cmd {
|
enum Cmd {
|
||||||
@ -384,7 +390,8 @@ struct QVkCommandBuffer : public QRhiCommandBuffer
|
|||||||
DebugMarkerEnd,
|
DebugMarkerEnd,
|
||||||
DebugMarkerInsert,
|
DebugMarkerInsert,
|
||||||
TransitionPassResources,
|
TransitionPassResources,
|
||||||
Dispatch
|
Dispatch,
|
||||||
|
ExecuteSecondary
|
||||||
};
|
};
|
||||||
Cmd cmd;
|
Cmd cmd;
|
||||||
|
|
||||||
@ -493,6 +500,7 @@ struct QVkCommandBuffer : public QRhiCommandBuffer
|
|||||||
} debugMarkerEnd;
|
} debugMarkerEnd;
|
||||||
struct {
|
struct {
|
||||||
VkDebugMarkerMarkerInfoEXT marker;
|
VkDebugMarkerMarkerInfoEXT marker;
|
||||||
|
int markerNameIndex;
|
||||||
} debugMarkerInsert;
|
} debugMarkerInsert;
|
||||||
struct {
|
struct {
|
||||||
int trackerIndex;
|
int trackerIndex;
|
||||||
@ -500,6 +508,9 @@ struct QVkCommandBuffer : public QRhiCommandBuffer
|
|||||||
struct {
|
struct {
|
||||||
int x, y, z;
|
int x, y, z;
|
||||||
} dispatch;
|
} dispatch;
|
||||||
|
struct {
|
||||||
|
VkCommandBuffer cb;
|
||||||
|
} executeSecondary;
|
||||||
} args;
|
} args;
|
||||||
};
|
};
|
||||||
QVector<Command> commands;
|
QVector<Command> commands;
|
||||||
@ -508,9 +519,10 @@ struct QVkCommandBuffer : public QRhiCommandBuffer
|
|||||||
|
|
||||||
void resetCommands() {
|
void resetCommands() {
|
||||||
commands.clear();
|
commands.clear();
|
||||||
|
resetPools();
|
||||||
|
|
||||||
passResTrackers.clear();
|
passResTrackers.clear();
|
||||||
currentPassResTrackerIndex = -1;
|
currentPassResTrackerIndex = -1;
|
||||||
resetPools();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetPools() {
|
void resetPools() {
|
||||||
@ -519,7 +531,7 @@ struct QVkCommandBuffer : public QRhiCommandBuffer
|
|||||||
pools.dynamicOffset.clear();
|
pools.dynamicOffset.clear();
|
||||||
pools.vertexBuffer.clear();
|
pools.vertexBuffer.clear();
|
||||||
pools.vertexBufferOffset.clear();
|
pools.vertexBufferOffset.clear();
|
||||||
pools.debugMarkerName.clear();
|
pools.debugMarkerData.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@ -528,7 +540,7 @@ struct QVkCommandBuffer : public QRhiCommandBuffer
|
|||||||
QVarLengthArray<uint32_t, 4> dynamicOffset;
|
QVarLengthArray<uint32_t, 4> dynamicOffset;
|
||||||
QVarLengthArray<VkBuffer, 4> vertexBuffer;
|
QVarLengthArray<VkBuffer, 4> vertexBuffer;
|
||||||
QVarLengthArray<VkDeviceSize, 4> vertexBufferOffset;
|
QVarLengthArray<VkDeviceSize, 4> vertexBufferOffset;
|
||||||
QVarLengthArray<QByteArray, 4> debugMarkerName;
|
QVarLengthArray<QByteArray, 4> debugMarkerData;
|
||||||
} pools;
|
} pools;
|
||||||
|
|
||||||
friend class QRhiVulkan;
|
friend class QRhiVulkan;
|
||||||
@ -592,7 +604,7 @@ struct QVkSwapChain : public QRhiSwapChain
|
|||||||
bool imageAcquired = false;
|
bool imageAcquired = false;
|
||||||
bool imageSemWaitable = false;
|
bool imageSemWaitable = false;
|
||||||
quint32 imageIndex = 0;
|
quint32 imageIndex = 0;
|
||||||
VkCommandBuffer cmdBuf = VK_NULL_HANDLE;
|
VkCommandBuffer cmdBuf = VK_NULL_HANDLE; // primary
|
||||||
VkFence cmdFence = VK_NULL_HANDLE;
|
VkFence cmdFence = VK_NULL_HANDLE;
|
||||||
bool cmdFenceWaitable = false;
|
bool cmdFenceWaitable = false;
|
||||||
int timestampQueryIndex = -1;
|
int timestampQueryIndex = -1;
|
||||||
@ -637,8 +649,8 @@ public:
|
|||||||
QRhiSwapChain *createSwapChain() override;
|
QRhiSwapChain *createSwapChain() override;
|
||||||
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
|
QRhi::FrameOpResult beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags) override;
|
||||||
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
|
QRhi::FrameOpResult endFrame(QRhiSwapChain *swapChain, QRhi::EndFrameFlags flags) override;
|
||||||
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb) override;
|
QRhi::FrameOpResult beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi::BeginFrameFlags flags) override;
|
||||||
QRhi::FrameOpResult endOffscreenFrame() override;
|
QRhi::FrameOpResult endOffscreenFrame(QRhi::EndFrameFlags flags) override;
|
||||||
QRhi::FrameOpResult finish() override;
|
QRhi::FrameOpResult finish() override;
|
||||||
|
|
||||||
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
void resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) override;
|
||||||
@ -727,9 +739,12 @@ public:
|
|||||||
VkShaderModule createShader(const QByteArray &spirv);
|
VkShaderModule createShader(const QByteArray &spirv);
|
||||||
|
|
||||||
void prepareNewFrame(QRhiCommandBuffer *cb);
|
void prepareNewFrame(QRhiCommandBuffer *cb);
|
||||||
QRhi::FrameOpResult startCommandBuffer(VkCommandBuffer *cb);
|
VkCommandBuffer startSecondaryCommandBuffer(QVkRenderTargetData *rtD = nullptr);
|
||||||
QRhi::FrameOpResult endAndSubmitCommandBuffer(VkCommandBuffer cb, VkFence cmdFence,
|
void endAndEnqueueSecondaryCommandBuffer(VkCommandBuffer cb, QVkCommandBuffer *cbD);
|
||||||
VkSemaphore *waitSem, VkSemaphore *signalSem);
|
void deferredReleaseSecondaryCommandBuffer(VkCommandBuffer cb);
|
||||||
|
QRhi::FrameOpResult startPrimaryCommandBuffer(VkCommandBuffer *cb);
|
||||||
|
QRhi::FrameOpResult endAndSubmitPrimaryCommandBuffer(VkCommandBuffer cb, VkFence cmdFence,
|
||||||
|
VkSemaphore *waitSem, VkSemaphore *signalSem);
|
||||||
void waitCommandCompletion(int frameSlot);
|
void waitCommandCompletion(int frameSlot);
|
||||||
VkDeviceSize subresUploadByteSize(const QRhiTextureSubresourceUploadDescription &subresDesc) const;
|
VkDeviceSize subresUploadByteSize(const QRhiTextureSubresourceUploadDescription &subresDesc) const;
|
||||||
using BufferImageCopyList = QVarLengthArray<VkBufferImageCopy, 16>;
|
using BufferImageCopyList = QVarLengthArray<VkBufferImageCopy, 16>;
|
||||||
@ -740,7 +755,7 @@ public:
|
|||||||
void enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates);
|
void enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates);
|
||||||
void executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD);
|
void executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD);
|
||||||
void enqueueTransitionPassResources(QVkCommandBuffer *cbD);
|
void enqueueTransitionPassResources(QVkCommandBuffer *cbD);
|
||||||
void recordCommandBuffer(QVkCommandBuffer *cbD);
|
void recordPrimaryCommandBuffer(QVkCommandBuffer *cbD);
|
||||||
void trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker,
|
void trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker,
|
||||||
QVkBuffer *bufD,
|
QVkBuffer *bufD,
|
||||||
int slot,
|
int slot,
|
||||||
@ -856,7 +871,8 @@ public:
|
|||||||
Sampler,
|
Sampler,
|
||||||
TextureRenderTarget,
|
TextureRenderTarget,
|
||||||
RenderPass,
|
RenderPass,
|
||||||
StagingBuffer
|
StagingBuffer,
|
||||||
|
CommandBuffer
|
||||||
};
|
};
|
||||||
Type type;
|
Type type;
|
||||||
int lastActiveFrameSlot; // -1 if not used otherwise 0..FRAMES_IN_FLIGHT-1
|
int lastActiveFrameSlot; // -1 if not used otherwise 0..FRAMES_IN_FLIGHT-1
|
||||||
@ -903,6 +919,9 @@ public:
|
|||||||
VkBuffer stagingBuffer;
|
VkBuffer stagingBuffer;
|
||||||
QVkAlloc stagingAllocation;
|
QVkAlloc stagingAllocation;
|
||||||
} stagingBuffer;
|
} stagingBuffer;
|
||||||
|
struct {
|
||||||
|
VkCommandBuffer cb;
|
||||||
|
} commandBuffer;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
QVector<DeferredReleaseEntry> releaseQueue;
|
QVector<DeferredReleaseEntry> releaseQueue;
|
||||||
|
@ -1689,7 +1689,7 @@ void QNetworkAccessManager::clearConnectionCache()
|
|||||||
\sa setAutoDeleteReplies,
|
\sa setAutoDeleteReplies,
|
||||||
QNetworkRequest::AutoDeleteReplyOnFinishAttribute
|
QNetworkRequest::AutoDeleteReplyOnFinishAttribute
|
||||||
*/
|
*/
|
||||||
bool QNetworkAccessManager::autoDeleteReplies()
|
bool QNetworkAccessManager::autoDeleteReplies() const
|
||||||
{
|
{
|
||||||
return d_func()->autoDeleteReplies;
|
return d_func()->autoDeleteReplies;
|
||||||
}
|
}
|
||||||
|
@ -167,7 +167,7 @@ public:
|
|||||||
void setRedirectPolicy(QNetworkRequest::RedirectPolicy policy);
|
void setRedirectPolicy(QNetworkRequest::RedirectPolicy policy);
|
||||||
QNetworkRequest::RedirectPolicy redirectPolicy() const;
|
QNetworkRequest::RedirectPolicy redirectPolicy() const;
|
||||||
|
|
||||||
bool autoDeleteReplies();
|
bool autoDeleteReplies() const;
|
||||||
void setAutoDeleteReplies(bool autoDelete);
|
void setAutoDeleteReplies(bool autoDelete);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
@ -1966,6 +1966,7 @@ void QAbstractItemView::mouseDoubleClickEvent(QMouseEvent *event)
|
|||||||
if ((event->button() == Qt::LeftButton) && !edit(persistent, DoubleClicked, event)
|
if ((event->button() == Qt::LeftButton) && !edit(persistent, DoubleClicked, event)
|
||||||
&& !style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, 0, this))
|
&& !style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, 0, this))
|
||||||
emit activated(persistent);
|
emit activated(persistent);
|
||||||
|
d->pressedIndex = QModelIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if QT_CONFIG(draganddrop)
|
#if QT_CONFIG(draganddrop)
|
||||||
|
@ -1943,6 +1943,7 @@ void QTreeView::mouseDoubleClickEvent(QMouseEvent *event)
|
|||||||
if (!style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, 0, this))
|
if (!style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, 0, this))
|
||||||
emit activated(persistent);
|
emit activated(persistent);
|
||||||
|
|
||||||
|
d->pressedIndex = QModelIndex();
|
||||||
d->executePostedLayout(); // we need to make sure viewItems is updated
|
d->executePostedLayout(); // we need to make sure viewItems is updated
|
||||||
if (d->itemsExpandable
|
if (d->itemsExpandable
|
||||||
&& d->expandsOnDoubleClick
|
&& d->expandsOnDoubleClick
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include <QtNetwork/qtcpserver.h>
|
#include <QtNetwork/qtcpserver.h>
|
||||||
#include <QtNetwork/qtcpsocket.h>
|
#include <QtNetwork/qtcpsocket.h>
|
||||||
#include <QtCore/qelapsedtimer.h>
|
#include <QtCore/qelapsedtimer.h>
|
||||||
|
#include <QtCore/qtimer.h>
|
||||||
|
|
||||||
#include <QtCore/qt_windows.h>
|
#include <QtCore/qt_windows.h>
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ class tst_NoQtEventLoop : public QObject
|
|||||||
private slots:
|
private slots:
|
||||||
void consumeMouseEvents();
|
void consumeMouseEvents();
|
||||||
void consumeSocketEvents();
|
void consumeSocketEvents();
|
||||||
|
void deliverEventsInLivelock();
|
||||||
};
|
};
|
||||||
|
|
||||||
class Window : public QRasterWindow
|
class Window : public QRasterWindow
|
||||||
@ -312,6 +313,34 @@ void tst_NoQtEventLoop::consumeSocketEvents()
|
|||||||
QVERIFY(server.hasPendingConnections());
|
QVERIFY(server.hasPendingConnections());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_NoQtEventLoop::deliverEventsInLivelock()
|
||||||
|
{
|
||||||
|
int argc = 1;
|
||||||
|
char *argv[] = { const_cast<char *>("test"), 0 };
|
||||||
|
QGuiApplication app(argc, argv);
|
||||||
|
|
||||||
|
QTimer livelockTimer;
|
||||||
|
livelockTimer.start(0);
|
||||||
|
QTimer::singleShot(100, Qt::CoarseTimer, &livelockTimer, &QTimer::stop);
|
||||||
|
|
||||||
|
QElapsedTimer elapsedTimer;
|
||||||
|
elapsedTimer.start();
|
||||||
|
|
||||||
|
// Exec own message loop
|
||||||
|
MSG msg;
|
||||||
|
forever {
|
||||||
|
if (elapsedTimer.hasExpired(3000) || !livelockTimer.isActive())
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||||
|
::TranslateMessage(&msg);
|
||||||
|
::DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVERIFY(!livelockTimer.isActive());
|
||||||
|
}
|
||||||
|
|
||||||
#include <tst_noqteventloop.moc>
|
#include <tst_noqteventloop.moc>
|
||||||
|
|
||||||
QTEST_APPLESS_MAIN(tst_NoQtEventLoop)
|
QTEST_APPLESS_MAIN(tst_NoQtEventLoop)
|
||||||
|
@ -124,6 +124,7 @@ QString graphicsApiName()
|
|||||||
QRhi::Flags rhiFlags = QRhi::EnableDebugMarkers;
|
QRhi::Flags rhiFlags = QRhi::EnableDebugMarkers;
|
||||||
int sampleCount = 1;
|
int sampleCount = 1;
|
||||||
QRhiSwapChain::Flags scFlags = 0;
|
QRhiSwapChain::Flags scFlags = 0;
|
||||||
|
QRhi::BeginFrameFlags beginFrameFlags = 0;
|
||||||
QRhi::EndFrameFlags endFrameFlags = 0;
|
QRhi::EndFrameFlags endFrameFlags = 0;
|
||||||
|
|
||||||
class Window : public QWindow
|
class Window : public QWindow
|
||||||
@ -375,7 +376,7 @@ void Window::render()
|
|||||||
// GPU/present, and that's what throttles the thread to the refresh rate.
|
// GPU/present, and that's what throttles the thread to the refresh rate.
|
||||||
// (except for OpenGL where it happens either in endFrame or somewhere else
|
// (except for OpenGL where it happens either in endFrame or somewhere else
|
||||||
// depending on the GL implementation)
|
// depending on the GL implementation)
|
||||||
QRhi::FrameOpResult r = m_r->beginFrame(m_sc);
|
QRhi::FrameOpResult r = m_r->beginFrame(m_sc, beginFrameFlags);
|
||||||
if (r == QRhi::FrameOpSwapChainOutOfDate) {
|
if (r == QRhi::FrameOpSwapChainOutOfDate) {
|
||||||
resizeSwapChain();
|
resizeSwapChain();
|
||||||
if (!m_hasSwapChain)
|
if (!m_hasSwapChain)
|
||||||
|
@ -71,6 +71,7 @@
|
|||||||
//#define READBACK_SWAPCHAIN
|
//#define READBACK_SWAPCHAIN
|
||||||
//#define NO_VSYNC
|
//#define NO_VSYNC
|
||||||
//#define USE_MIN_SWAPCHAIN_BUFFERS
|
//#define USE_MIN_SWAPCHAIN_BUFFERS
|
||||||
|
//#define DECLARE_EXT_CONTENTS
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
TriangleRenderer triRenderer;
|
TriangleRenderer triRenderer;
|
||||||
@ -118,6 +119,10 @@ void preInit()
|
|||||||
scFlags |= QRhiSwapChain::MinimalBufferCount;
|
scFlags |= QRhiSwapChain::MinimalBufferCount;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DECLARE_EXT_CONTENTS
|
||||||
|
beginFrameFlags |= QRhi::ExternalContentsInPass;
|
||||||
|
#endif
|
||||||
|
|
||||||
// For OpenGL some of these are incorporated into the QSurfaceFormat by
|
// For OpenGL some of these are incorporated into the QSurfaceFormat by
|
||||||
// examplefw.h after returning from here as that is out of the RHI's control.
|
// examplefw.h after returning from here as that is out of the RHI's control.
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user