2017-02-12 14:08:52 +00:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
|
|
|
** Copyright (C) 2017 The Qt Company Ltd.
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
|
|
|
**
|
|
|
|
** This file is part of the examples of the Qt Toolkit.
|
|
|
|
**
|
|
|
|
** $QT_BEGIN_LICENSE:BSD$
|
|
|
|
** Commercial License Usage
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
|
|
|
**
|
|
|
|
** BSD License Usage
|
|
|
|
** Alternatively, you may use this file under the terms of the BSD license
|
|
|
|
** as follows:
|
|
|
|
**
|
|
|
|
** "Redistribution and use in source and binary forms, with or without
|
|
|
|
** modification, are permitted provided that the following conditions are
|
|
|
|
** met:
|
|
|
|
** * Redistributions of source code must retain the above copyright
|
|
|
|
** notice, this list of conditions and the following disclaimer.
|
|
|
|
** * Redistributions in binary form must reproduce the above copyright
|
|
|
|
** notice, this list of conditions and the following disclaimer in
|
|
|
|
** the documentation and/or other materials provided with the
|
|
|
|
** distribution.
|
|
|
|
** * Neither the name of The Qt Company Ltd nor the names of its
|
|
|
|
** contributors may be used to endorse or promote products derived
|
|
|
|
** from this software without specific prior written permission.
|
|
|
|
**
|
|
|
|
**
|
|
|
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
|
|
|
**
|
|
|
|
** $QT_END_LICENSE$
|
|
|
|
**
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include "hellovulkanwidget.h"
|
|
|
|
#include <QVulkanFunctions>
|
|
|
|
#include <QApplication>
|
|
|
|
#include <QVBoxLayout>
|
2017-03-30 07:43:07 +00:00
|
|
|
#include <QPlainTextEdit>
|
2017-02-12 14:08:52 +00:00
|
|
|
#include <QPushButton>
|
|
|
|
#include <QLCDNumber>
|
|
|
|
#include <QFileDialog>
|
|
|
|
#include <QMessageBox>
|
2017-03-30 07:43:07 +00:00
|
|
|
#include <QTabWidget>
|
2017-02-12 14:08:52 +00:00
|
|
|
|
2017-03-30 07:43:07 +00:00
|
|
|
MainWindow::MainWindow(VulkanWindow *w, QPlainTextEdit *logWidget)
|
2017-02-12 14:08:52 +00:00
|
|
|
: m_window(w)
|
|
|
|
{
|
|
|
|
QWidget *wrapper = QWidget::createWindowContainer(w);
|
|
|
|
|
2017-03-30 07:43:07 +00:00
|
|
|
m_info = new QPlainTextEdit;
|
2017-02-12 14:08:52 +00:00
|
|
|
m_info->setReadOnly(true);
|
|
|
|
|
|
|
|
m_number = new QLCDNumber(3);
|
|
|
|
m_number->setSegmentStyle(QLCDNumber::Filled);
|
|
|
|
|
|
|
|
QPushButton *grabButton = new QPushButton(tr("&Grab"));
|
|
|
|
grabButton->setFocusPolicy(Qt::NoFocus);
|
|
|
|
|
|
|
|
connect(grabButton, &QPushButton::clicked, this, &MainWindow::onGrabRequested);
|
|
|
|
|
|
|
|
QPushButton *quitButton = new QPushButton(tr("&Quit"));
|
|
|
|
quitButton->setFocusPolicy(Qt::NoFocus);
|
|
|
|
|
|
|
|
connect(quitButton, &QPushButton::clicked, qApp, &QCoreApplication::quit);
|
|
|
|
|
|
|
|
QVBoxLayout *layout = new QVBoxLayout;
|
2017-03-30 07:43:07 +00:00
|
|
|
m_infoTab = new QTabWidget(this);
|
|
|
|
m_infoTab->addTab(m_info, tr("Vulkan Info"));
|
|
|
|
m_infoTab->addTab(logWidget, tr("Debug Log"));
|
|
|
|
layout->addWidget(m_infoTab, 2);
|
2017-02-12 14:08:52 +00:00
|
|
|
layout->addWidget(m_number, 1);
|
|
|
|
layout->addWidget(wrapper, 5);
|
|
|
|
layout->addWidget(grabButton, 1);
|
|
|
|
layout->addWidget(quitButton, 1);
|
|
|
|
setLayout(layout);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::onVulkanInfoReceived(const QString &text)
|
|
|
|
{
|
2017-03-30 07:43:07 +00:00
|
|
|
m_info->setPlainText(text);
|
2017-02-12 14:08:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::onFrameQueued(int colorValue)
|
|
|
|
{
|
|
|
|
m_number->display(colorValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainWindow::onGrabRequested()
|
|
|
|
{
|
|
|
|
if (!m_window->supportsGrab()) {
|
|
|
|
QMessageBox::warning(this, tr("Cannot grab"), tr("This swapchain does not support readbacks."));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QImage img = m_window->grab();
|
|
|
|
|
|
|
|
// Our startNextFrame() implementation is synchronous so img is ready to be
|
|
|
|
// used right here.
|
|
|
|
|
|
|
|
QFileDialog fd(this);
|
|
|
|
fd.setAcceptMode(QFileDialog::AcceptSave);
|
|
|
|
fd.setDefaultSuffix("png");
|
|
|
|
fd.selectFile("test.png");
|
|
|
|
if (fd.exec() == QDialog::Accepted)
|
|
|
|
img.save(fd.selectedFiles().first());
|
|
|
|
}
|
|
|
|
|
|
|
|
QVulkanWindowRenderer *VulkanWindow::createRenderer()
|
|
|
|
{
|
|
|
|
return new VulkanRenderer(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
VulkanRenderer::VulkanRenderer(VulkanWindow *w)
|
|
|
|
: TriangleRenderer(w)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void VulkanRenderer::initResources()
|
|
|
|
{
|
|
|
|
TriangleRenderer::initResources();
|
|
|
|
|
|
|
|
QVulkanInstance *inst = m_window->vulkanInstance();
|
|
|
|
m_devFuncs = inst->deviceFunctions(m_window->device());
|
|
|
|
|
|
|
|
QString info;
|
|
|
|
info += QString().sprintf("Number of physical devices: %d\n", m_window->availablePhysicalDevices().count());
|
|
|
|
|
|
|
|
QVulkanFunctions *f = inst->functions();
|
|
|
|
VkPhysicalDeviceProperties props;
|
|
|
|
f->vkGetPhysicalDeviceProperties(m_window->physicalDevice(), &props);
|
|
|
|
info += QString().sprintf("Active physical device name: '%s' version %d.%d.%d\nAPI version %d.%d.%d\n",
|
|
|
|
props.deviceName,
|
|
|
|
VK_VERSION_MAJOR(props.driverVersion), VK_VERSION_MINOR(props.driverVersion),
|
|
|
|
VK_VERSION_PATCH(props.driverVersion),
|
|
|
|
VK_VERSION_MAJOR(props.apiVersion), VK_VERSION_MINOR(props.apiVersion),
|
|
|
|
VK_VERSION_PATCH(props.apiVersion));
|
|
|
|
|
|
|
|
info += QStringLiteral("Supported instance layers:\n");
|
|
|
|
for (const QVulkanLayer &layer : inst->supportedLayers())
|
|
|
|
info += QString().sprintf(" %s v%u\n", layer.name.constData(), layer.version);
|
|
|
|
info += QStringLiteral("Enabled instance layers:\n");
|
|
|
|
for (const QByteArray &layer : inst->layers())
|
|
|
|
info += QString().sprintf(" %s\n", layer.constData());
|
|
|
|
|
|
|
|
info += QStringLiteral("Supported instance extensions:\n");
|
|
|
|
for (const QVulkanExtension &ext : inst->supportedExtensions())
|
|
|
|
info += QString().sprintf(" %s v%u\n", ext.name.constData(), ext.version);
|
|
|
|
info += QStringLiteral("Enabled instance extensions:\n");
|
|
|
|
for (const QByteArray &ext : inst->extensions())
|
|
|
|
info += QString().sprintf(" %s\n", ext.constData());
|
|
|
|
|
|
|
|
info += QString().sprintf("Color format: %u\nDepth-stencil format: %u\n",
|
|
|
|
m_window->colorFormat(), m_window->depthStencilFormat());
|
|
|
|
|
|
|
|
info += QStringLiteral("Supported sample counts:");
|
2017-05-22 08:23:16 +00:00
|
|
|
const QVector<int> sampleCounts = m_window->supportedSampleCounts();
|
2017-02-12 14:08:52 +00:00
|
|
|
for (int count : sampleCounts)
|
|
|
|
info += QLatin1Char(' ') + QString::number(count);
|
|
|
|
info += QLatin1Char('\n');
|
|
|
|
|
|
|
|
emit static_cast<VulkanWindow *>(m_window)->vulkanInfoReceived(info);
|
|
|
|
}
|
|
|
|
|
|
|
|
void VulkanRenderer::startNextFrame()
|
|
|
|
{
|
|
|
|
TriangleRenderer::startNextFrame();
|
|
|
|
emit static_cast<VulkanWindow *>(m_window)->frameQueued(int(m_rotation) % 360);
|
|
|
|
}
|