Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qgraphicsframecapturemetal.mm
Go to the documentation of this file.
1
// Copyright (C) 2023 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
// Qt-Security score:significant reason:default
4
5
#
include
"qgraphicsframecapturemetal_p_p.h"
6
#
include
<
QtCore
/
qurl
.
h
>
7
#
include
"Metal/Metal.h"
8
#
include
"qglobal.h"
9
#
include
<
QtGui
/
rhi
/
qrhi
.
h
>
10
#
include
<
QtGui
/
rhi
/
qrhi_platform
.
h
>
11
12
QT_BEGIN_NAMESPACE
13
14
Q_LOGGING_CATEGORY
(lcGraphicsFrameCapture,
"qt.gui.graphicsframecapture"
)
15
16
#
if
__has_feature
(
objc_arc
)
17
#
error
ARC
not
supported
18
#
endif
19
20
uint QGraphicsFrameCaptureMetal::frameNumber = 0;
21
22
QGraphicsFrameCaptureMetal::QGraphicsFrameCaptureMetal()
23
{
24
qputenv(
"METAL_CAPTURE_ENABLED"
, QByteArrayLiteral(
"1"
));
25
26
m_captureDescriptor = [MTLCaptureDescriptor
new
];
27
}
28
29
QGraphicsFrameCaptureMetal::~QGraphicsFrameCaptureMetal()
30
{
31
#
if
defined
(
Q_OS_MACOS
)
&&
QT_CONFIG
(
process
)
32
if
(m_process) {
33
m_process->terminate();
34
delete
m_process;
35
}
36
#
endif
37
[m_captureDescriptor release];
38
}
39
40
void
QGraphicsFrameCaptureMetal::setRhi(QRhi *rhi)
41
{
42
if
(!rhi)
43
return
;
44
45
QRhi::Implementation backend = rhi->backend();
46
const
QRhiNativeHandles *nh = rhi->nativeHandles();
47
48
switch
(backend) {
49
case
QRhi::Implementation::Metal: {
50
const
QRhiMetalNativeHandles *mtlnh =
static_cast
<
const
QRhiMetalNativeHandles *>(nh);
51
if
(mtlnh->cmdQueue) {
52
m_captureDescriptor.captureObject = mtlnh->cmdQueue;
53
}
else
if
(mtlnh->dev) {
54
m_captureDescriptor.captureObject = mtlnh->dev;
55
}
else
{
56
qCWarning(lcGraphicsFrameCapture) <<
"No valid Metal Device or Metal Command Queue found"
;
57
m_initialized =
false
;
58
return
;
59
}
60
break
;
61
}
62
default
: {
63
qCWarning(lcGraphicsFrameCapture) <<
"Invalid handles were provided. MTLCaptureManager works only with Metal API"
;
64
m_initialized =
false
;
65
return
;
66
break
;
67
}
68
}
69
70
if
(!m_captureManager) {
71
m_captureManager = MTLCaptureManager.sharedCaptureManager;
72
bool
supportDocs = [m_captureManager supportsDestination:MTLCaptureDestinationGPUTraceDocument];
73
if
(supportDocs) {
74
m_captureDescriptor.destination = MTLCaptureDestinationGPUTraceDocument;
75
m_initialized =
true
;
76
}
77
}
78
}
79
80
void
QGraphicsFrameCaptureMetal::startCaptureFrame()
81
{
82
if
(!initialized()) {
83
qCWarning(lcGraphicsFrameCapture) <<
"Capturing on Metal was not initialized. Starting capturing can not be done."
;
84
return
;
85
}
86
87
if
(isCapturing()) {
88
qCWarning(lcGraphicsFrameCapture) <<
"A frame capture is already in progress,"
89
"will not initiate another one until QGraphicsFrameCapture::endCaptureFrame is called."
;
90
return
;
91
}
92
93
updateCaptureFileName();
94
NSError *error;
95
if
(![m_captureManager startCaptureWithDescriptor:m_captureDescriptor error:&error]) {
96
QString errorMsg = QString::fromNSString(error.localizedDescription);
97
qCWarning(lcGraphicsFrameCapture,
"Failed to start capture : %s"
, qPrintable(errorMsg));
98
}
99
}
100
101
void
QGraphicsFrameCaptureMetal::endCaptureFrame()
102
{
103
if
(!initialized()) {
104
qCWarning(lcGraphicsFrameCapture) <<
"Capturing on Metal was not initialized. End capturing can not be done."
;
105
return
;
106
}
107
108
if
(!isCapturing()) {
109
qCWarning(lcGraphicsFrameCapture) <<
"A call to QGraphicsFrameCapture::endCaptureFrame can not be done"
110
" without a call to QGraphicsFrameCapture::startCaptureFrame"
;
111
return
;
112
}
113
114
[m_captureManager stopCapture];
115
m_capturedFilesNames.append(QString::fromNSString(m_traceURL.path));
116
frameNumber++;
117
}
118
119
bool
QGraphicsFrameCaptureMetal::initialized()
const
120
{
121
return
m_initialized;
122
}
123
124
bool
QGraphicsFrameCaptureMetal::isCapturing()
const
125
{
126
if
(!initialized()) {
127
qCWarning(lcGraphicsFrameCapture) <<
"Capturing on Metal was not initialized. Can not query if capturing is in progress or not."
;
128
return
false
;
129
}
130
131
return
[m_captureManager isCapturing];
132
}
133
134
void
QGraphicsFrameCaptureMetal::openCapture()
135
{
136
#
if
defined
(
Q_OS_MACOS
)
137
#
if
!
QT_CONFIG
(
process
)
138
qFatal(
"QGraphicsFrameCapture requires QProcess on macOS"
);
139
#
else
140
if
(!initialized()) {
141
qCWarning(lcGraphicsFrameCapture) <<
"Capturing on Metal was not initialized. Can not open XCode with a valid capture."
;
142
return
;
143
}
144
145
if
(!m_process) {
146
m_process =
new
QProcess();
147
m_process->setProgram(QStringLiteral(
"xed"
));
148
QStringList args;
149
args.append(QUrl::fromNSURL(m_traceURL).toLocalFile());
150
m_process->setArguments(args);
151
}
152
153
m_process->kill();
154
m_process->start();
155
#
endif
156
#
endif
157
}
158
159
void
QGraphicsFrameCaptureMetal::updateCaptureFileName()
160
{
161
m_traceURL = QUrl::fromLocalFile(m_capturePath + u"/" + m_capturePrefix + u"_"
162
+ QString::number(frameNumber) + u".gputrace")
163
.toNSURL();
164
// We need to remove the trace file if it already existed else MTLCaptureManager
165
// will fail to.
166
if
([NSFileManager.defaultManager fileExistsAtPath:m_traceURL.path])
167
[NSFileManager.defaultManager removeItemAtURL:m_traceURL error:nil];
168
169
m_captureDescriptor.outputURL = m_traceURL;
170
}
171
172
QT_END_NAMESPACE
__has_feature
#define __has_feature(x)
Definition
qcompilerdetection.h:447
Q_LOGGING_CATEGORY
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
qtbase
src
gui
util
qgraphicsframecapturemetal.mm
Generated on
for Qt by
1.18.0