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
rhi_support.cpp
Go to the documentation of this file.
1
// Copyright (C) 2026 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4
#
include
"rhi_support_p.h"
5
6
#
include
<
QtMultimedia
/
private
/
qvideotexturehelper_p
.
h
>
7
#
include
<
QtMultimedia
/
qvideoframeformat
.
h
>
8
9
#
include
<
QtCore
/
qfile
.
h
>
10
11
QT_BEGIN_NAMESPACE
12
13
namespace
QtMultimediaTest
{
14
15
using
namespace
Qt
::
Literals
;
16
17
std
::
unique_ptr
<
QRhi
>
createNullRhi
()
18
{
19
QRhiNullInitParams params;
20
return
std::unique_ptr<QRhi>{ QRhi::create(QRhi::Null, ¶ms) };
21
}
22
23
#
if
QT_CONFIG
(
opengl
)
24
q23
::
expected
<
OffscreenGlRhi
,
QString
>
createOffscreenGlRhi
()
25
{
26
std
::
unique_ptr
<
QOffscreenSurface
>
fallbackSurface
{
27
QRhiGles2InitParams
::
newFallbackSurface
(),
28
};
29
30
QRhiGles2InitParams
glParams
;
31
glParams
.
format
=
QSurfaceFormat
::
defaultFormat
();
32
glParams
.
fallbackSurface
=
fallbackSurface
.
get
();
33
std
::
unique_ptr
<
QRhi
>
rhi
{
34
QRhi
::
create
(
QRhi
::
OpenGLES2
, &
glParams
),
35
};
36
if
(!
rhi
)
37
return
q23
::
unexpected
(u"QRhi::create failed"_s);
38
39
return
OffscreenGlRhi
{
40
std
::
move
(
fallbackSurface
),
41
std
::
move
(
rhi
),
42
};
43
}
44
45
std
::
unique_ptr
<
QRhi
>
createGles2Rhi
(
QOffscreenSurface
*
fallbackSurface
)
46
{
47
QRhiGles2InitParams
params
;
48
params
.
fallbackSurface
=
fallbackSurface
;
49
return
std
::
unique_ptr
<
QRhi
>{
QRhi
::
create
(
QRhi
::
OpenGLES2
, &
params
) };
50
}
51
#
endif
52
53
#
if
QT_CONFIG
(
vulkan
)
54
q23
::
expected
<
OffscreenVulkanRhi
,
QString
>
55
createOffscreenVulkanRhi
(
const
QByteArrayList
&
deviceExtensions
)
56
{
57
auto
vulkanInstance
=
std
::
make_unique
<
QVulkanInstance
>();
58
vulkanInstance
->
setApiVersion
(
QVersionNumber
(1, 1));
59
vulkanInstance
->
setExtensions
(
QRhiVulkanInitParams
::
preferredInstanceExtensions
());
60
if
(!
vulkanInstance
->
create
())
61
return
q23
::
unexpected
(u"QVulkanInstance::create failed"_s);
62
63
QRhiVulkanInitParams
params
;
64
params
.
inst
=
vulkanInstance
.
get
();
65
params
.
deviceExtensions
=
deviceExtensions
;
66
std
::
unique_ptr
<
QRhi
>
rhi
{
67
QRhi
::
create
(
QRhi
::
Vulkan
, &
params
),
68
};
69
if
(!
rhi
) {
70
return
q23
::
unexpected
(u"QRhi::create failed"_s);
71
}
72
return
OffscreenVulkanRhi
{
73
std
::
move
(
vulkanInstance
),
74
std
::
move
(
rhi
),
75
};
76
}
77
#
endif
78
79
#
if
QT_CONFIG
(
metal
)
80
std
::
unique_ptr
<
QRhi
>
createOffscreenMetalRhi
()
81
{
82
QRhiMetalInitParams
metalParams
;
83
return
std
::
unique_ptr
<
QRhi
>(
QRhi
::
create
(
QRhi
::
Metal
, &
metalParams
));
84
}
85
#
endif
86
87
#
if
defined
(
Q_OS_WIN
)
88
std
::
unique_ptr
<
QRhi
>
createOffscreenD3D11Rhi
()
89
{
90
QRhiD3D11InitParams
params
;
91
return
std
::
unique_ptr
<
QRhi
>(
QRhi
::
create
(
QRhi
::
D3D11
, &
params
));
92
}
93
94
std
::
unique_ptr
<
QRhi
>
createWarpD3D11Rhi
(
const
QWindowsD3D11TestDeviceContext
&
warpDevice
)
95
{
96
QRhiD3D11NativeHandles
nativeHandles
;
97
nativeHandles
.
dev
=
warpDevice
.
device
.
Get
();
98
nativeHandles
.
context
=
warpDevice
.
context
.
Get
();
99
100
QRhiD3D11InitParams
params
;
101
return
std
::
unique_ptr
<
QRhi
>{
QRhi
::
create
(
QRhi
::
D3D11
, &
params
, {}, &
nativeHandles
) };
102
}
103
104
std
::
unique_ptr
<
QRhi
>
createD3D12Rhi
()
105
{
106
QRhiD3D12InitParams
params
;
107
return
std
::
unique_ptr
<
QRhi
>{
QRhi
::
create
(
QRhi
::
D3D12
, &
params
) };
108
}
109
110
#
endif
111
112
q23
::
expected
<
QByteArray
,
QString
>
readBackPlane
(QRhi &rhi, quint64 handle, QSize planeSize,
113
QRhiTexture::Format format)
114
{
115
std::unique_ptr<QRhiTexture> texture(
116
rhi.newTexture(format, planeSize, 1, QRhiTexture::UsedAsTransferSource));
117
if
(!texture->createFrom(QRhiTexture::NativeTexture{ handle, 0 }))
118
return
q23::unexpected(u"QRhiTexture::createFrom failed"_s);
119
120
QRhiResourceUpdateBatch *batch = rhi.nextResourceUpdateBatch();
121
QRhiReadbackResult result;
122
batch->readBackTexture(texture.get(), &result);
123
124
QRhiCommandBuffer *cb =
nullptr
;
125
if
(rhi.beginOffscreenFrame(&cb) != QRhi::FrameOpSuccess || !cb)
126
return
q23::unexpected(u"QRhi::beginOffscreenFrame failed"_s);
127
cb->resourceUpdate(batch);
128
rhi.endOffscreenFrame();
129
130
return
result.data;
131
}
132
133
#
if
QT_CONFIG
(
opengl
)
134
135
namespace
{
136
137
q23
::
expected
<
QShader
,
QString
>
loadShader
(
const
QString
&
path
)
138
{
139
QFile
file
(
path
);
140
if
(!
file
.
open
(
QIODevice
::
ReadOnly
))
141
return
q23
::
unexpected
(u"Could not open shader file: "_s +
path
);
142
QShader
shader
=
QShader
::
fromSerialized
(
file
.
readAll
());
143
if
(!
shader
.
isValid
())
144
return
q23
::
unexpected
(u"Invalid/unsupported shader file: "_s +
path
);
145
return
shader
;
146
}
147
148
}
// namespace
149
150
// Unlike readBackPlane(), EXTERNAL_OES textures can't be read back directly: they're only
151
// consumable by a shader (samplerExternalOES). Renders the texture through a full-screen quad
152
// using this module's own externalsampler shader into a plain RGBA8 target, then reads that back.
153
q23
::
expected
<
QByteArray
,
QString
>
readBackExternalOesTexture
(
QRhi
&
rhi
,
quint64
handle
,
QSize
size
)
154
{
155
std
::
unique_ptr
<
QRhiTexture
>
sourceTexture
{
156
rhi
.
newTexture
(
QRhiTexture
::
RGBA8
,
size
, 1,
QRhiTexture
::
ExternalOES
),
157
};
158
if
(!
sourceTexture
->
createFrom
(
QRhiTexture
::
NativeTexture
{
handle
, 0 }))
159
return
q23
::
unexpected
(u"Failed to wrap the native handle as an ExternalOES QRhiTexture"_s);
160
161
std
::
unique_ptr
<
QRhiTexture
>
targetTexture
{
162
rhi
.
newTexture
(
QRhiTexture
::
RGBA8
,
size
, 1,
163
QRhiTexture
::
RenderTarget
|
QRhiTexture
::
UsedAsTransferSource
),
164
};
165
if
(!
targetTexture
->
create
())
166
return
q23
::
unexpected
(u"Failed to create the readback render target texture"_s);
167
168
QRhiColorAttachment
colorAttachment
(
targetTexture
.
get
());
169
std
::
unique_ptr
<
QRhiTextureRenderTarget
>
renderTarget
{
170
rhi
.
newTextureRenderTarget
(
QRhiTextureRenderTargetDescription
(
colorAttachment
)),
171
};
172
std
::
unique_ptr
<
QRhiRenderPassDescriptor
>
renderPassDescriptor
{
173
renderTarget
->
newCompatibleRenderPassDescriptor
(),
174
};
175
renderTarget
->
setRenderPassDescriptor
(
renderPassDescriptor
.
get
());
176
if
(!
renderTarget
->
create
())
177
return
q23
::
unexpected
(u"Failed to create the readback render target"_s);
178
179
const
QVideoFrameFormat
format
(
size
,
QVideoFrameFormat
::
Format_SamplerExternalOES
);
180
auto
vertexShader
=
loadShader
(
QVideoTextureHelper
::
vertexShaderFileName
(
format
));
181
if
(!
vertexShader
)
182
return
q23
::
unexpected
(
vertexShader
.
error
());
183
auto
fragmentShader
=
loadShader
(
QVideoTextureHelper
::
fragmentShaderFileName
(
format
, &
rhi
));
184
if
(!
fragmentShader
)
185
return
q23
::
unexpected
(
fragmentShader
.
error
());
186
187
std
::
unique_ptr
<
QRhiSampler
>
sampler
{
188
rhi
.
newSampler
(
QRhiSampler
::
Linear
,
QRhiSampler
::
Linear
,
QRhiSampler
::
None
,
189
QRhiSampler
::
ClampToEdge
,
QRhiSampler
::
ClampToEdge
),
190
};
191
if
(!
sampler
->
create
())
192
return
q23
::
unexpected
(u"Failed to create the sampler"_s);
193
194
std
::
unique_ptr
<
QRhiBuffer
>
uniformBuffer
{
195
rhi
.
newBuffer
(
QRhiBuffer
::
Dynamic
,
QRhiBuffer
::
UniformBuffer
,
196
sizeof
(
QVideoTextureHelper
::
UniformData
)),
197
};
198
if
(!
uniformBuffer
->
create
())
199
return
q23
::
unexpected
(u"Failed to create the uniform buffer"_s);
200
201
std
::
unique_ptr
<
QRhiShaderResourceBindings
>
srb
(
rhi
.
newShaderResourceBindings
());
202
srb
->
setBindings
({
203
QRhiShaderResourceBinding
::
uniformBuffer
(
204
0,
205
QRhiShaderResourceBinding
::
VertexStage
206
|
QRhiShaderResourceBinding
::
FragmentStage
,
207
uniformBuffer
.
get
()),
208
QRhiShaderResourceBinding
::
sampledTexture
(1,
QRhiShaderResourceBinding
::
FragmentStage
,
209
sourceTexture
.
get
(),
sampler
.
get
()),
210
});
211
if
(!
srb
->
create
())
212
return
q23
::
unexpected
(u"Failed to create the shader resource bindings"_s);
213
214
// A single full-screen quad (vertexPosition: vec4, vertexTexCoord: vec2, interleaved),
215
// matching the vertex layout every one of this module's video shaders expects.
216
static
constexpr
float
vertexData
[] = {
217
// x, y, z, w, u, v
218
-1.f, -1.f, 0.f, 1.f, 0.f, 0.f,
//
219
1.f, -1.f, 0.f, 1.f, 1.f, 0.f,
//
220
-1.f, 1.f, 0.f, 1.f, 0.f, 1.f,
//
221
1.f, 1.f, 0.f, 1.f, 1.f, 1.f,
222
};
223
std
::
unique_ptr
<
QRhiBuffer
>
vertexBuffer
{
224
rhi
.
newBuffer
(
QRhiBuffer
::
Immutable
,
QRhiBuffer
::
VertexBuffer
,
sizeof
(
vertexData
)),
225
};
226
if
(!
vertexBuffer
->
create
())
227
return
q23
::
unexpected
(u"Failed to create the vertex buffer"_s);
228
229
QRhiVertexInputLayout
inputLayout
;
230
inputLayout
.
setBindings
({ { 6 *
sizeof
(
float
) } });
231
inputLayout
.
setAttributes
({
232
{ 0, 0,
QRhiVertexInputAttribute
::
Float4
, 0 },
233
{ 0, 1,
QRhiVertexInputAttribute
::
Float2
, 4 *
sizeof
(
float
) },
234
});
235
236
std
::
unique_ptr
<
QRhiGraphicsPipeline
>
pipeline
(
rhi
.
newGraphicsPipeline
());
237
pipeline
->
setShaderStages
({
238
{
QRhiShaderStage
::
Vertex
, *
vertexShader
},
239
{
QRhiShaderStage
::
Fragment
, *
fragmentShader
},
240
});
241
pipeline
->
setVertexInputLayout
(
inputLayout
);
242
pipeline
->
setShaderResourceBindings
(
srb
.
get
());
243
pipeline
->
setRenderPassDescriptor
(
renderPassDescriptor
.
get
());
244
pipeline
->
setTopology
(
QRhiGraphicsPipeline
::
TriangleStrip
);
245
if
(!
pipeline
->
create
())
246
return
q23
::
unexpected
(u"Failed to create the graphics pipeline"_s);
247
248
QRhiCommandBuffer
*
cb
=
nullptr
;
249
if
(
rhi
.
beginOffscreenFrame
(&
cb
) !=
QRhi
::
FrameOpSuccess
|| !
cb
)
250
return
q23
::
unexpected
(u"QRhi::beginOffscreenFrame failed"_s);
251
252
QRhiResourceUpdateBatch
*
batch
=
rhi
.
nextResourceUpdateBatch
();
253
batch
->
uploadStaticBuffer
(
vertexBuffer
.
get
(),
vertexData
);
254
255
QVideoTextureHelper
::
UniformData
uniformData
{};
256
const
QMatrix4x4
identity
;
257
memcpy
(
uniformData
.
transformMatrix
,
identity
.
constData
(),
sizeof
(
uniformData
.
transformMatrix
));
258
memcpy
(
uniformData
.
colorMatrix
,
identity
.
constData
(),
sizeof
(
uniformData
.
colorMatrix
));
259
uniformData
.
opacity
= 1.f;
260
batch
->
updateDynamicBuffer
(
uniformBuffer
.
get
(), 0,
sizeof
(
uniformData
), &
uniformData
);
261
262
cb
->
beginPass
(
renderTarget
.
get
(),
Qt
::
black
, { 1.0f, 0 },
batch
);
263
cb
->
setGraphicsPipeline
(
pipeline
.
get
());
264
cb
->
setViewport
({ 0, 0,
float
(
size
.
width
()),
float
(
size
.
height
()) });
265
cb
->
setShaderResources
(
srb
.
get
());
266
const
QRhiCommandBuffer
::
VertexInput
vertexBinding
(
vertexBuffer
.
get
(), 0);
267
cb
->
setVertexInput
(0, 1, &
vertexBinding
);
268
cb
->
draw
(4);
269
cb
->
endPass
();
270
271
QRhiReadbackResult
result
;
272
QRhiResourceUpdateBatch
*
readbackBatch
=
rhi
.
nextResourceUpdateBatch
();
273
readbackBatch
->
readBackTexture
(
targetTexture
.
get
(), &
result
);
274
cb
->
resourceUpdate
(
readbackBatch
);
275
276
rhi
.
endOffscreenFrame
();
277
278
return
result
.
data
;
279
}
280
281
#
endif
// QT_CONFIG(opengl)
282
283
}
// namespace QtMultimediaTest
284
285
QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
QtMultimediaTest
Definition
framegrabber.cpp:20
QtMultimediaTest::readBackPlane
q23::expected< QByteArray, QString > readBackPlane(QRhi &rhi, quint64 handle, QSize planeSize, QRhiTexture::Format format)
Definition
rhi_support.cpp:112
QtMultimediaTest::createNullRhi
std::unique_ptr< QRhi > createNullRhi()
Definition
rhi_support.cpp:17
qtmultimedia
src
multimediatestlib
rhi_support.cpp
Generated on
for Qt by
1.18.0