diff options
Diffstat (limited to 'src/gui/vulkan')
-rw-r--r-- | src/gui/vulkan/qvulkanfunctions.cpp | 21 | ||||
-rw-r--r-- | src/gui/vulkan/qvulkaninstance.cpp | 97 | ||||
-rw-r--r-- | src/gui/vulkan/qvulkanwindow.cpp | 94 |
3 files changed, 17 insertions, 195 deletions
diff --git a/src/gui/vulkan/qvulkanfunctions.cpp b/src/gui/vulkan/qvulkanfunctions.cpp index c5f9616d20..73dbeb9ab6 100644 --- a/src/gui/vulkan/qvulkanfunctions.cpp +++ b/src/gui/vulkan/qvulkanfunctions.cpp @@ -66,16 +66,7 @@ QT_BEGIN_NAMESPACE The typical usage is the following: - \code - void Window::render() - { - QVulkanInstance *inst = vulkanInstance(); - QVulkanFunctions *f = inst->functions(); - ... - VkResult err = f->vkAllocateCommandBuffers(device, &cmdBufInfo, &cmdBuf); - ... - } - \endcode + \snippet code/src_gui_vulkan_qvulkanfunctions.cpp 0 \note Windowing system interface (WSI) specifics and extensions are excluded. This class only covers core Vulkan commands, with the exception @@ -118,15 +109,7 @@ QT_BEGIN_NAMESPACE The typical usage is the following: - \code - void Window::render() - { - QVulkanInstance *inst = vulkanInstance(); - QVulkanDeviceFunctions *df = inst->deviceFunctions(device); - VkResult err = df->vkAllocateCommandBuffers(device, &cmdBufInfo, &cmdBuf); - ... - } - \endcode + \snippet code/src_gui_vulkan_qvulkanfunctions.cpp 1 The QVulkanDeviceFunctions object specific to the provided VkDevice is created when QVulkanInstance::deviceFunctions() is first called with the diff --git a/src/gui/vulkan/qvulkaninstance.cpp b/src/gui/vulkan/qvulkaninstance.cpp index 8236d9625a..000c2b8caa 100644 --- a/src/gui/vulkan/qvulkaninstance.cpp +++ b/src/gui/vulkan/qvulkaninstance.cpp @@ -97,22 +97,7 @@ QT_BEGIN_NAMESPACE calling QWindow::setVulkanInstance(). Thus a typical application pattern is the following: - \code - int main(int argc, char **argv) - { - QGuiApplication app(argc, argv); - - QVulkanInstance inst; - if (!inst.create()) - return 1; - - ... - window->setVulkanInstance(&inst); - window->show(); - - return app.exec(); - } - \endcode + \snippet code/src_gui_vulkan_qvulkaninstance.cpp 0 \section1 Configuration @@ -138,31 +123,12 @@ QT_BEGIN_NAMESPACE For example, to enable the standard validation layers, one could do the following: - \code - QVulkanInstance inst; - - // Enable validation layer, if supported. Messages go to qDebug by default. - inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation"); - - bool ok = inst.create(); - if (!ok) - ... // Vulkan not available - if (!inst.layers().contains("VK_LAYER_LUNARG_standard_validation")) - ... // validation layer not available - \endcode + \snippet code/src_gui_vulkan_qvulkaninstance.cpp 1 Or, alternatively, to make decisions before attempting to create a Vulkan instance: - \code - QVulkanInstance inst; - - if (inst.supportedLayers().contains("VK_LAYER_LUNARG_standard_validation")) - ... - - bool ok = inst.create(); - ... - \endcode + \snippet code/src_gui_vulkan_qvulkaninstance.cpp 2 \section1 Adopting an Existing Instance @@ -229,62 +195,7 @@ QT_BEGIN_NAMESPACE The following is the basic outline of creating a Vulkan-capable QWindow: - \code - class VulkanWindow : public QWindow - { - public: - VulkanWindow() { - setSurfaceType(VulkanSurface); - } - - void exposeEvent(QExposeEvent *) { - if (isExposed()) { - if (!m_initialized) { - m_initialized = true; - // initialize device, swapchain, etc. - QVulkanInstance *inst = vulkanInstance(); - QVulkanFunctions *f = inst->functions(); - uint32_t devCount = 0; - f->vkEnumeratePhysicalDevices(inst->vkInstance(), &devCount, nullptr); - ... - // build the first frame - render(); - } - } - } - - bool event(QEvent *e) { - if (e->type == QEvent::UpdateRequest) - render(); - return QWindow::event(e); - } - - void render() { - ... - requestUpdate(); // render continuously - } - - private: - bool m_initialized = false; - }; - - int main(int argc, char **argv) - { - QGuiApplication app(argc, argv); - - QVulkanInstance inst; - if (!inst.create()) { - qWarning("Vulkan not available"); - return 1; - } - - VulkanWindow window; - window.showMaximized(); - - return app.exec(); - - } - \endcode + \snippet code/src_gui_vulkan_qvulkaninstance.cpp 3 \note In addition to expose, a well-behaving window implementation will also have to take care of additional events like resize and diff --git a/src/gui/vulkan/qvulkanwindow.cpp b/src/gui/vulkan/qvulkanwindow.cpp index e45a16170e..6d12377a60 100644 --- a/src/gui/vulkan/qvulkanwindow.cpp +++ b/src/gui/vulkan/qvulkanwindow.cpp @@ -74,60 +74,7 @@ Q_LOGGING_CATEGORY(lcGuiVk, "qt.vulkan") A typical application using QVulkanWindow may look like the following: - \code - class VulkanRenderer : public QVulkanWindowRenderer - { - public: - VulkanRenderer(QVulkanWindow *w) : m_window(w) { } - - void initResources() override - { - m_devFuncs = m_window->vulkanInstance()->deviceFunctions(m_window->device()); - ... - } - void initSwapChainResources() override { ... } - void releaseSwapChainResources() override { ... } - void releaseResources() override { ... } - - void startNextFrame() override - { - VkCommandBuffer cmdBuf = m_window->currentCommandBuffer(); - ... - m_devFuncs->vkCmdBeginRenderPass(...); - ... - m_window->frameReady(); - } - - private: - QVulkanWindow *m_window; - QVulkanDeviceFunctions *m_devFuncs; - }; - - class VulkanWindow : public QVulkanWindow - { - public: - QVulkanWindowRenderer *createRenderer() override { - return new VulkanRenderer(this); - } - }; - - int main(int argc, char *argv[]) - { - QGuiApplication app(argc, argv); - - QVulkanInstance inst; - // enable the standard validation layers, when available - inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation"); - if (!inst.create()) - qFatal("Failed to create Vulkan instance: %d", inst.errorCode()); - - VulkanWindow w; - w.setVulkanInstance(&inst); - w.showMaximized(); - - return app.exec(); - } - \endcode + \snippet code/src_gui_vulkan_qvulkanwindow.cpp 0 As it can be seen in the example, the main patterns in QVulkanWindow usage are: @@ -989,7 +936,7 @@ bool QVulkanWindowPrivate::createDefaultRenderPass() attDesc[1].samples = sampleCount; attDesc[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; attDesc[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attDesc[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attDesc[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; attDesc[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; attDesc[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; attDesc[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; @@ -999,7 +946,7 @@ bool QVulkanWindowPrivate::createDefaultRenderPass() attDesc[2].format = colorFormat; attDesc[2].samples = sampleCount; attDesc[2].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attDesc[2].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attDesc[2].storeOp = VK_ATTACHMENT_STORE_OP_STORE; attDesc[2].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; attDesc[2].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; attDesc[2].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; @@ -2164,8 +2111,8 @@ void QVulkanWindowPrivate::addReadback() barrier.image = frameGrabImage; devFuncs->vkCmdPipelineBarrier(image.cmdBuf, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_HOST_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier); } @@ -2298,6 +2245,11 @@ uint32_t QVulkanWindow::hostVisibleMemoryIndex() const \note Calling this function is only valid from the invocation of QVulkanWindowRenderer::initResources() up until QVulkanWindowRenderer::releaseResources(). + + \note It is not guaranteed that this memory type is always suitable. The + correct, cross-implementation solution - especially for device local images + - is to manually pick a memory type after checking the mask returned from + \c{vkGetImageMemoryRequirements}. */ uint32_t QVulkanWindow::deviceLocalMemoryIndex() const { @@ -2434,18 +2386,7 @@ VkFramebuffer QVulkanWindow::currentFramebuffer() const concurrentFrameCount(). Such arrays can then be indexed by the value returned from this function. - \code - class Renderer { - ... - VkDescriptorBufferInfo m_uniformBufInfo[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT]; - }; - - void Renderer::startNextFrame() - { - VkDescriptorBufferInfo &uniformBufInfo(m_uniformBufInfo[m_window->currentFrame()]); - ... - } - \endcode + \snippet code/src_gui_vulkan_qvulkanwindow.cpp 1 \note This function must only be called from within startNextFrame() and, in case of asynchronous command generation, up until the call to frameReady(). @@ -2472,20 +2413,7 @@ int QVulkanWindow::currentFrame() const \note The value is constant for the entire lifetime of the QVulkanWindow. - \code - class Renderer { - ... - VkDescriptorBufferInfo m_uniformBufInfo[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT]; - }; - - void Renderer::startNextFrame() - { - const int count = m_window->concurrentFrameCount(); - for (int i = 0; i < count; ++i) - m_uniformBufInfo[i] = ... - ... - } - \endcode + \snippet code/src_gui_vulkan_qvulkanwindow.cpp 2 \sa currentFrame() */ |