4#include <QtCore/qcoreapplication.h>
5#include <QtCore/qfile.h>
6#include <QtCore/qfileinfo.h>
7#include <QtCore/qlist.h>
8#include <QtCore/qmap.h>
9#include <QtCore/qxmlstream.h>
44 void parseFeatureRequire(
const QString &versionDefine);
46 Command parseCommand();
47 TypedName parseParamOrProto(
const QString &
tag);
51 QXmlStreamReader m_reader;
64 m_reader.setDevice(&m_file);
67 m_versionCommandMapping.
clear();
69 while (!m_reader.atEnd()) {
71 if (m_reader.isStartElement()) {
82void VkSpecParser::skip()
85 while (!m_reader.atEnd()) {
87 if (m_reader.isEndElement() && m_reader.name() ==
tag)
92void VkSpecParser::parseFeature()
101 api = attr.value().toString().
trimmed();
103 versionName = attr.value().toString().
trimmed();
107 while (!m_reader.atEnd()) {
109 if (m_reader.isEndElement() && m_reader.name() ==
QStringLiteral(
"feature"))
111 if (m_reader.isStartElement() && m_reader.name() ==
QStringLiteral(
"require")) {
113 parseFeatureRequire(versionName);
118void VkSpecParser::parseFeatureRequire(
const QString &versionDefine)
123 while (!m_reader.atEnd()) {
125 if (m_reader.isEndElement() && m_reader.name() ==
QStringLiteral(
"require"))
127 if (m_reader.isStartElement() && m_reader.name() ==
QStringLiteral(
"command")) {
130 m_versionCommandMapping[versionDefine].append(attr.value().toString().trimmed());
136void VkSpecParser::parseCommands()
141 while (!m_reader.atEnd()) {
143 if (m_reader.isEndElement() && m_reader.name() ==
QStringLiteral(
"commands"))
145 if (m_reader.isStartElement() && m_reader.name() ==
QStringLiteral(
"command")) {
146 const Command
c = parseCommand();
147 if (!
c.cmd.name.isEmpty())
163 while (!m_reader.atEnd()) {
165 if (m_reader.isEndElement() && m_reader.name() ==
QStringLiteral(
"command"))
167 if (m_reader.isStartElement()) {
170 if (m_reader.name() == protoStr) {
171 c.cmd = parseParamOrProto(protoStr);
172 }
else if (m_reader.name() == paramStr) {
173 c.args.append(parseParamOrProto(paramStr));
180 c.deviceLevel =
false;
181 if (!
c.args.isEmpty()) {
187 if (dispatchableDeviceAndChildTypes.contains(
c.args[0].type)
190 c.deviceLevel =
true;
201 while (!m_reader.atEnd()) {
203 if (m_reader.isEndElement() && m_reader.name() ==
tag)
205 if (m_reader.isStartElement()) {
207 t.name = parseName();
212 auto text = m_reader.text().trimmed();
215 t.typeSuffix +=
text;
217 if (!
t.type.isEmpty())
228QString VkSpecParser::parseName()
231 while (!m_reader.atEnd()) {
233 if (m_reader.isEndElement() && m_reader.name() ==
QStringLiteral(
"name"))
235 name += m_reader.text();
237 return name.trimmed();
245 if (!
c.args.isEmpty()) {
254 (
a.type.endsWith(u
'*') ?
"" :
" "),
270 if (!
c.args.isEmpty()) {
307 m_str +=
"\n// This file is automatically generated by qvkgen. Do not edit.\n";
323 static const char *
s =
325"#ifndef QVULKANFUNCTIONS_H\n"
326"#define QVULKANFUNCTIONS_H\n"
329"#pragma qt_no_master_include\n"
332"#include <QtGui/qtguiglobal.h>\n"
334"#if QT_CONFIG(vulkan) || defined(Q_QDOC)\n"
336"#ifndef VK_NO_PROTOTYPES\n"
337"#define VK_NO_PROTOTYPES\n"
339"#include <vulkan/vulkan.h>\n"
341"#include <QtCore/qscopedpointer.h>\n"
343"QT_BEGIN_NAMESPACE\n"
345"class QVulkanInstance;\n"
346"class QVulkanFunctionsPrivate;\n"
347"class QVulkanDeviceFunctionsPrivate;\n"
349"class Q_GUI_EXPORT QVulkanFunctions\n"
352" ~QVulkanFunctions();\n"
356" Q_DISABLE_COPY(QVulkanFunctions)\n"
357" QVulkanFunctions(QVulkanInstance *inst);\n"
359" QScopedPointer<QVulkanFunctionsPrivate> d_ptr;\n"
360" friend class QVulkanInstance;\n"
363"class Q_GUI_EXPORT QVulkanDeviceFunctions\n"
366" ~QVulkanDeviceFunctions();\n"
370" Q_DISABLE_COPY(QVulkanDeviceFunctions)\n"
371" QVulkanDeviceFunctions(QVulkanInstance *inst, VkDevice device);\n"
373" QScopedPointer<QVulkanDeviceFunctionsPrivate> d_ptr;\n"
374" friend class QVulkanInstance;\n"
379"#endif // QT_CONFIG(vulkan) || defined(Q_QDOC)\n"
381"#endif // QVULKANFUNCTIONS_H\n";
386 const QStringList &coreFunctionsInVersion = versionCommandMapping[version];
387 instCmdStr +=
"#if " + version +
"\n";
388 devCmdStr +=
"#if " + version +
"\n";
390 if (!coreFunctionsInVersion.contains(
c.cmd.name))
393 QString *
dst =
c.deviceLevel ? &devCmdStr : &instCmdStr;
398 instCmdStr +=
"#endif\n";
399 devCmdStr +=
"#endif\n";
420 static const char *
s =
422"#ifndef QVULKANFUNCTIONS_P_H\n"
423"#define QVULKANFUNCTIONS_P_H\n"
429"// This file is not part of the Qt API. It exists purely as an\n"
430"// implementation detail. This header file may change from version to\n"
431"// version without notice, or even be removed.\n"
436"#include \"qvulkanfunctions.h\"\n"
438"QT_BEGIN_NAMESPACE\n"
440"class QVulkanInstance;\n"
442"class QVulkanFunctionsPrivate\n"
445" QVulkanFunctionsPrivate(QVulkanInstance *inst);\n"
447" PFN_vkVoidFunction m_funcs[%d];\n"
450"class QVulkanDeviceFunctionsPrivate\n"
453" QVulkanDeviceFunctionsPrivate(QVulkanInstance *inst, VkDevice device);\n"
455" PFN_vkVoidFunction m_funcs[%d];\n"
460"#endif // QVULKANFUNCTIONS_P_H\n";
462 int devLevelCount = 0;
463 int instLevelCount = 0;
465 const QStringList &coreFunctionsInVersion = versionCommandMapping[version];
467 if (!coreFunctionsInVersion.contains(
c.cmd.name))
493 static const char s[] =
495"#include \"qvulkanfunctions_p.h\"\n"
496"#include \"qvulkaninstance.h\"\n"
498"#include <QtCore/private/qoffsetstringarray_p.h>\n"
500"QT_BEGIN_NAMESPACE\n"
502"QVulkanFunctionsPrivate::QVulkanFunctionsPrivate(QVulkanInstance *inst)\n"
504" static constexpr auto funcNames = qOffsetStringArray(\n"
507" static_assert(std::extent_v<decltype(m_funcs)> == size_t(funcNames.count()));\n"
508" for (int i = 0; i < funcNames.count(); ++i) {\n"
509" m_funcs[i] = inst->getInstanceProcAddr(funcNames.at(i));\n"
510" if (i < %d && !m_funcs[i])\n"
511" qWarning(\"QVulkanFunctions: Failed to resolve %%s\", funcNames.at(i));\n"
515"QVulkanDeviceFunctionsPrivate::QVulkanDeviceFunctionsPrivate(QVulkanInstance *inst, VkDevice device)\n"
517" QVulkanFunctions *f = inst->functions();\n"
519" static constexpr auto funcNames = qOffsetStringArray(\n"
522" static_assert(std::extent_v<decltype(m_funcs)> == size_t(funcNames.count()));\n"
523" for (int i = 0; i < funcNames.count(); ++i) {\n"
524" m_funcs[i] = f->vkGetDeviceProcAddr(device, funcNames.at(i));\n"
525" if (i < %d && !m_funcs[i])\n"
526" qWarning(\"QVulkanDeviceFunctions: Failed to resolve %%s\", funcNames.at(i));\n"
538 int vulkan10DevCount = 0;
539 int vulkan10InstCount = 0;
542 const QStringList &coreFunctionsInVersion = versionCommandMapping[version];
543 instCmdWrapperStr +=
"\n#if " + version +
"\n";
544 devCmdWrapperStr +=
"\n#if " + version +
"\n";
546 if (!coreFunctionsInVersion.contains(
c.cmd.name))
549 QString *
dst =
c.deviceLevel ? &devCmdWrapperStr : &instCmdWrapperStr;
550 int *idx =
c.deviceLevel ? &devIdx : &instIdx;
551 *
dst +=
funcSig(
c,
c.deviceLevel ?
"QVulkanDeviceFunctions" :
"QVulkanFunctions");
557 dst =
c.deviceLevel ? &devCmdNamesStr : &instCmdNamesStr;
563 vulkan10InstCount = instIdx;
564 vulkan10DevCount = devIdx;
566 instCmdWrapperStr +=
"#endif\n\n";
567 devCmdWrapperStr +=
"#endif\n\n";
570 if (devCmdNamesStr.
size() > 2)
571 devCmdNamesStr.
chop(2);
572 if (instCmdNamesStr.
size() > 2)
573 instCmdNamesStr.
chop(2);
593 qWarning(
"Usage: qvkgen input_vk_xml input_license_header output_base\n"
594 " For example: qvkgen vulkan/vk.xml vulkan/qvulkanfunctions.header vulkan/qvulkanfunctions");
615 if (ignoredFuncs.contains(
commands[
i].cmd.name))
QByteArray get(const QString &fn)
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
QByteArray & replace(qsizetype index, qsizetype len, const char *s, qsizetype alen)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
void setFileName(const QString &name)
Sets the name of the file.
QString fileName() const override
Returns the name set by setFileName() or to the QFile constructors.
void append(parameter_type t)
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
void chop(qsizetype n)
Removes n characters from the end of the string.
qsizetype size() const
Returns the number of characters in this string.
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
QString trimmed() const &
QByteArray toUtf8() const &
static QString static QString asprintf(const char *format,...) Q_ATTRIBUTE_FORMAT_PRINTF(1
void setFileName(const QString &fn)
QList< Command > commands() const
QMap< QString, QStringList > versionCommandMapping() const
AudioChannelLayoutTag tag
GLboolean GLboolean GLboolean GLboolean a
[7]
GLsizei const GLubyte * commands
#define qPrintable(string)
#define QStringLiteral(str)
QString funcCall(const VkSpecParser::Command &c, int idx)
bool genVulkanFunctionsH(const QList< VkSpecParser::Command > &commands, const QMap< QString, QStringList > &versionCommandMapping, const QString &licHeaderFn, const QString &outputBase)
bool genVulkanFunctionsPH(const QList< VkSpecParser::Command > &commands, const QMap< QString, QStringList > &versionCommandMapping, const QString &licHeaderFn, const QString &outputBase)
bool genVulkanFunctionsPC(const QList< VkSpecParser::Command > &commands, const QMap< QString, QStringList > &versionCommandMapping, const QString &licHeaderFn, const QString &outputBase)
QString funcSig(const VkSpecParser::Command &c, const char *className=nullptr)
static const QStringList VERSIONS
const char className[16]
[1]
QApplication app(argc, argv)
[0]