1 | // Copyright (C) 2020 Klaralvdalens Datakonsult AB (KDAB). |
2 | // Copyright (C) 2016 Paul Lemire <paul.lemire350@gmail.com> |
3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
4 | |
5 | #include "commandexecuter_p.h" |
6 | |
7 | #include <Qt3DCore/private/qabstractaspect_p.h> |
8 | #include <Qt3DCore/qbackendnode.h> |
9 | #include <Qt3DRender/private/nodemanagers_p.h> |
10 | #include <Qt3DRender/private/geometryrenderermanager_p.h> |
11 | #include <Qt3DRender/private/stringtoint_p.h> |
12 | #include <QJsonObject> |
13 | #include <QJsonDocument> |
14 | #include <QJsonArray> |
15 | #include <submissioncontext_p.h> |
16 | #include <renderview_p.h> |
17 | #include <rendercommand_p.h> |
18 | #include <renderer_p.h> |
19 | #include <submissioncontext_p.h> |
20 | |
21 | QT_BEGIN_NAMESPACE |
22 | |
23 | namespace Qt3DRender { |
24 | |
25 | namespace DebugRhi { |
26 | |
27 | namespace { |
28 | |
29 | #if 0 // unused for now |
30 | |
31 | template<typename Type> |
32 | QJsonObject typeToJsonObj(const Type &) noexcept |
33 | { |
34 | return QJsonObject(); |
35 | } |
36 | |
37 | template<typename Type> |
38 | QJsonValue typeToJsonValue(const Type &t) noexcept |
39 | { |
40 | Q_UNUSED(t); |
41 | return QJsonValue(); |
42 | } |
43 | |
44 | template<> |
45 | QJsonObject typeToJsonObj<QRectF>(const QRectF &rect) noexcept |
46 | { |
47 | QJsonObject obj; |
48 | |
49 | obj.insert(QLatin1String("x" ), rect.x()); |
50 | obj.insert(QLatin1String("y" ), rect.y()); |
51 | obj.insert(QLatin1String("width" ), rect.width()); |
52 | obj.insert(QLatin1String("height" ), rect.height()); |
53 | |
54 | return obj; |
55 | } |
56 | |
57 | template<> |
58 | QJsonValue typeToJsonValue<QRectF>(const QRectF &rect) noexcept |
59 | { |
60 | QJsonArray value; |
61 | |
62 | value.push_back(rect.x()); |
63 | value.push_back(rect.y()); |
64 | value.push_back(rect.width()); |
65 | value.push_back(rect.height()); |
66 | |
67 | return value; |
68 | } |
69 | |
70 | template<> |
71 | QJsonObject typeToJsonObj<QSize>(const QSize &s) noexcept |
72 | { |
73 | QJsonObject obj; |
74 | |
75 | obj.insert(QLatin1String("width" ), s.width()); |
76 | obj.insert(QLatin1String("height" ), s.height()); |
77 | |
78 | return obj; |
79 | } |
80 | |
81 | template<> |
82 | QJsonValue typeToJsonValue<QSize>(const QSize &s) noexcept |
83 | { |
84 | QJsonArray value; |
85 | |
86 | value.push_back(s.width()); |
87 | value.push_back(s.height()); |
88 | |
89 | return value; |
90 | } |
91 | |
92 | template<> |
93 | QJsonObject typeToJsonObj<QVector3D>(const QVector3D &v) noexcept |
94 | { |
95 | QJsonObject obj; |
96 | |
97 | obj.insert(QLatin1String("x" ), v.x()); |
98 | obj.insert(QLatin1String("y" ), v.y()); |
99 | obj.insert(QLatin1String("z" ), v.z()); |
100 | |
101 | return obj; |
102 | } |
103 | |
104 | template<> |
105 | QJsonValue typeToJsonValue<QVector3D>(const QVector3D &v) noexcept |
106 | { |
107 | QJsonArray value; |
108 | |
109 | value.push_back(v.x()); |
110 | value.push_back(v.y()); |
111 | value.push_back(v.z()); |
112 | |
113 | return value; |
114 | } |
115 | |
116 | template<> |
117 | QJsonObject typeToJsonObj<Qt3DCore::QNodeId>(const Qt3DCore::QNodeId &v) noexcept |
118 | { |
119 | QJsonObject obj; |
120 | obj.insert(QLatin1String("id" ), qint64(v.id())); |
121 | return obj; |
122 | } |
123 | |
124 | template<> |
125 | QJsonValue typeToJsonValue<Qt3DCore::QNodeId>(const Qt3DCore::QNodeId &v) noexcept |
126 | { |
127 | QJsonValue value(qint64(v.id())); |
128 | return value; |
129 | } |
130 | |
131 | template<> |
132 | QJsonObject typeToJsonObj<QVector4D>(const QVector4D &v) noexcept |
133 | { |
134 | QJsonObject obj; |
135 | |
136 | obj.insert(QLatin1String("x" ), v.x()); |
137 | obj.insert(QLatin1String("y" ), v.y()); |
138 | obj.insert(QLatin1String("z" ), v.z()); |
139 | obj.insert(QLatin1String("w" ), v.w()); |
140 | |
141 | return obj; |
142 | } |
143 | |
144 | template<> |
145 | QJsonValue typeToJsonValue<QVector4D>(const QVector4D &v) noexcept |
146 | { |
147 | QJsonArray value; |
148 | |
149 | value.push_back(v.x()); |
150 | value.push_back(v.y()); |
151 | value.push_back(v.z()); |
152 | value.push_back(v.w()); |
153 | |
154 | return value; |
155 | } |
156 | |
157 | template<> |
158 | QJsonObject typeToJsonObj<QMatrix4x4>(const QMatrix4x4 &v) noexcept |
159 | { |
160 | QJsonObject obj; |
161 | |
162 | obj.insert(QLatin1String("row 0" ), typeToJsonObj(v.row(0))); |
163 | obj.insert(QLatin1String("row 1" ), typeToJsonObj(v.row(0))); |
164 | obj.insert(QLatin1String("row 2" ), typeToJsonObj(v.row(0))); |
165 | obj.insert(QLatin1String("row 3" ), typeToJsonObj(v.row(0))); |
166 | |
167 | return obj; |
168 | } |
169 | |
170 | template<> |
171 | QJsonValue typeToJsonValue<QMatrix4x4>(const QMatrix4x4 &v) noexcept |
172 | { |
173 | QJsonArray value; |
174 | |
175 | value.push_back(typeToJsonValue(v.row(0))); |
176 | value.push_back(typeToJsonValue(v.row(1))); |
177 | value.push_back(typeToJsonValue(v.row(2))); |
178 | value.push_back(typeToJsonValue(v.row(3))); |
179 | |
180 | return value; |
181 | } |
182 | |
183 | template<> |
184 | QJsonValue typeToJsonValue<QVariant>(const QVariant &v) noexcept |
185 | { |
186 | const int nodeTypeId = qMetaTypeId<Qt3DCore::QNodeId>(); |
187 | |
188 | if (v.userType() == nodeTypeId) |
189 | return typeToJsonValue(v.value<Qt3DCore::QNodeId>()); |
190 | |
191 | switch (v.userType()) { |
192 | case QMetaType::QVector3D: |
193 | return typeToJsonValue(v.value<QVector3D>()); |
194 | case QMetaType::QVector4D: |
195 | return typeToJsonValue(v.value<QVector4D>()); |
196 | case QMetaType::QMatrix4x4: |
197 | return typeToJsonValue(v.value<QMatrix4x4>()); |
198 | default: |
199 | return QJsonValue::fromVariant(v); |
200 | } |
201 | } |
202 | |
203 | template<typename Handle, typename Manager> |
204 | QJsonObject backendNodeToJSon(Handle handle, Manager *manager) noexcept |
205 | { |
206 | Qt3DCore::QBackendNode *node = manager->data(handle); |
207 | QJsonObject obj; |
208 | Qt3DCore::QNodeId id; |
209 | if (node != nullptr) |
210 | id = node->peerId(); |
211 | obj.insert(QLatin1String("id" ), qint64(id.id())); |
212 | return obj; |
213 | } |
214 | |
215 | QJsonObject parameterPackToJson(const Render::Rhi::ShaderParameterPack &pack) noexcept |
216 | { |
217 | QJsonObject obj; |
218 | |
219 | const Render::Rhi::PackUniformHash &uniforms = pack.uniforms(); |
220 | QJsonArray uniformsArray; |
221 | for (qsizetype i = 0, m = uniforms.keys.size(); i < m; ++i) { |
222 | QJsonObject uniformObj; |
223 | uniformObj.insert(QLatin1String("name" ), Render::StringToInt::lookupString(uniforms.keys.at(i))); |
224 | const Render::UniformValue::ValueType type = uniforms.values.at(i).valueType(); |
225 | uniformObj.insert(QLatin1String("type" ), |
226 | type == Render::UniformValue::ScalarValue |
227 | ? QLatin1String("value" ) |
228 | : QLatin1String("texture" )); |
229 | uniformsArray.push_back(uniformObj); |
230 | } |
231 | obj.insert(QLatin1String("uniforms" ), uniformsArray); |
232 | |
233 | QJsonArray texturesArray; |
234 | const std::vector<Render::Rhi::ShaderParameterPack::NamedResource> &textures = pack.textures(); |
235 | for (const auto & texture : textures) { |
236 | QJsonObject textureObj; |
237 | textureObj.insert(QLatin1String("name" ), Render::StringToInt::lookupString(texture.glslNameId)); |
238 | textureObj.insert(QLatin1String("id" ), qint64(texture.nodeId.id())); |
239 | texturesArray.push_back(textureObj); |
240 | } |
241 | obj.insert(QLatin1String("textures" ), texturesArray); |
242 | |
243 | const std::vector<Render::Rhi::BlockToUBO> &ubos = pack.uniformBuffers(); |
244 | QJsonArray ubosArray; |
245 | for (const auto &ubo : ubos) { |
246 | QJsonObject uboObj; |
247 | uboObj.insert(QLatin1String("index" ), ubo.m_blockIndex); |
248 | uboObj.insert(QLatin1String("bufferId" ), qint64(ubo.m_bufferID.id())); |
249 | ubosArray.push_back(uboObj); |
250 | |
251 | } |
252 | obj.insert(QLatin1String("ubos" ), ubosArray); |
253 | |
254 | const std::vector<Render::Rhi::BlockToSSBO> &ssbos = pack.shaderStorageBuffers(); |
255 | QJsonArray ssbosArray; |
256 | for (const auto &ssbo : ssbos) { |
257 | QJsonObject ssboObj; |
258 | ssboObj.insert(QLatin1String("index" ), ssbo.m_blockIndex); |
259 | ssboObj.insert(QLatin1String("bufferId" ), qint64(ssbo.m_bufferID.id())); |
260 | ssbosArray.push_back(ssboObj); |
261 | } |
262 | obj.insert(QLatin1String("ssbos" ), ssbosArray); |
263 | |
264 | return obj; |
265 | } |
266 | |
267 | #endif // 0 |
268 | |
269 | } // anonymous |
270 | |
271 | CommandExecuter::CommandExecuter(Render::Rhi::Renderer *renderer) : m_renderer(renderer) { |
272 | Q_UNUSED(m_renderer) |
273 | } |
274 | |
275 | // Render thread |
276 | void CommandExecuter::performAsynchronousCommandExecution( |
277 | const std::vector<Render::Rhi::RenderView *> &views) |
278 | { |
279 | Q_UNUSED(views); |
280 | RHI_UNIMPLEMENTED; |
281 | //* QMutexLocker lock(&m_pendingCommandsMutex); |
282 | //* const std::vector<Qt3DCore::Debug::AsynchronousCommandReply *> shellCommands = |
283 | //std::move(m_pendingCommands); |
284 | //* lock.unlock(); |
285 | //* |
286 | //* for (auto *reply : shellCommands) { |
287 | //* if (reply->commandName() == QLatin1String("glinfo")) { |
288 | //* QJsonObject replyObj; |
289 | //* const GraphicsApiFilterData *contextInfo = |
290 | //m_renderer->submissionContext()->contextInfo(); |
291 | //* if (contextInfo != nullptr) { |
292 | //* replyObj.insert(QLatin1String("api"), |
293 | //* contextInfo->m_api == QGraphicsApiFilter::OpenGL |
294 | //* ? QLatin1String("OpenGL") |
295 | //* : QLatin1String("OpenGLES")); |
296 | //* const QString versionString = |
297 | //* QString::number(contextInfo->m_major) |
298 | //* + QStringLiteral(".") |
299 | //* + QString::number(contextInfo->m_minor); |
300 | //* replyObj.insert(QLatin1String("version"), versionString); |
301 | //* replyObj.insert(QLatin1String("profile"), |
302 | //* contextInfo->m_profile == QGraphicsApiFilter::CoreProfile |
303 | //* ? QLatin1String("Core") |
304 | //* : contextInfo->m_profile == |
305 | //QGraphicsApiFilter::CompatibilityProfile |
306 | //* ? QLatin1String("Compatibility") |
307 | //* : QLatin1String("None")); |
308 | //* } |
309 | //* reply->setData(QJsonDocument(replyObj).toJson()); |
310 | //* } else if (reply->commandName() == QLatin1String("rendercommands")) { |
311 | //* QJsonObject replyObj; |
312 | //* |
313 | //* QJsonArray viewArray; |
314 | //* for (Render::Rhi::RenderView *v : views) { |
315 | //* QJsonObject viewObj; |
316 | //* viewObj.insert(QLatin1String("viewport"), typeToJsonValue(v->viewport())); |
317 | //* viewObj.insert(QLatin1String("surfaceSize"), |
318 | //typeToJsonValue(v->surfaceSize())); |
319 | //* viewObj.insert(QLatin1String("devicePixelRatio"), v->devicePixelRatio()); |
320 | //* viewObj.insert(QLatin1String("noDraw"), v->noDraw()); |
321 | //* viewObj.insert(QLatin1String("frustumCulling"), v->frustumCulling()); |
322 | //* viewObj.insert(QLatin1String("compute"), v->isCompute()); |
323 | //* viewObj.insert(QLatin1String("clearDepthValue"), v->clearDepthValue()); |
324 | //* viewObj.insert(QLatin1String("clearStencilValue"), v->clearStencilValue()); |
325 | //* |
326 | //* QJsonArray renderCommandsArray; |
327 | //* for (Render::Rhi::RenderCommand &c : v->commands()) { |
328 | //* QJsonObject commandObj; |
329 | //* Render::NodeManagers *nodeManagers = m_renderer->nodeManagers(); |
330 | //* commandObj.insert(QLatin1String("shader"), |
331 | //typeToJsonValue(QVariant::fromValue(c.m_shaderId))); |
332 | //* commandObj.insert(QLatin1String("vao"), double(c.m_vao.handle())); |
333 | //* commandObj.insert(QLatin1String("instanceCount"), c.m_instanceCount); |
334 | //* commandObj.insert(QLatin1String("geometry"), |
335 | //backendNodeToJSon(c.m_geometry, nodeManagers->geometryManager())); |
336 | //* commandObj.insert(QLatin1String("geometryRenderer"), |
337 | //backendNodeToJSon(c.m_geometryRenderer, nodeManagers->geometryRendererManager())); |
338 | //* commandObj.insert(QLatin1String("shaderParameterPack"), |
339 | //parameterPackToJson(c.m_parameterPack)); |
340 | //* |
341 | //* renderCommandsArray.push_back(commandObj); |
342 | //* } |
343 | //* viewObj.insert(QLatin1String("commands"), renderCommandsArray); |
344 | //* viewArray.push_back(viewObj); |
345 | //* } |
346 | //* |
347 | //* replyObj.insert(QLatin1String("renderViews"), viewArray); |
348 | //* reply->setData(QJsonDocument(replyObj).toJson()); |
349 | //* } |
350 | //* reply->setFinished(true); |
351 | //* } |
352 | } |
353 | |
354 | // Main thread |
355 | QVariant CommandExecuter::executeCommand(const QStringList &args) |
356 | { |
357 | Q_UNUSED(args); |
358 | RHI_UNIMPLEMENTED; |
359 | //* // Note: The replies will be deleted by the AspectCommandDebugger |
360 | //* if (args.length() > 0 && |
361 | //* (args.first() == QLatin1String("glinfo") || |
362 | //* args.first() == QLatin1String("rendercommands"))) { |
363 | //* auto reply = new Qt3DCore::Debug::AsynchronousCommandReply(args.first()); |
364 | //* QMutexLocker lock(&m_pendingCommandsMutex); |
365 | //* m_pendingCommands.push_back(reply); |
366 | //* return QVariant::fromValue(reply); |
367 | //* } |
368 | return QVariant(); |
369 | } |
370 | |
371 | } // DebugRhi |
372 | |
373 | } // Qt3DRenderer |
374 | |
375 | QT_END_NAMESPACE |
376 | |