Sophie

Sophie

distrib > Mageia > 7 > armv7hl > media > core-updates > by-pkgid > d5e62c01ae8d1e579463c6a871dd44bf > files > 1868

qtbase5-doc-5.12.6-2.mga7.noarch.rpm

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>renderer.cpp Example File | Qt GUI 5.12.6</title>
  <link rel="stylesheet" type="text/css" href="style/offline-simple.css" />
  <script type="text/javascript">
    document.getElementsByTagName("link").item(0).setAttribute("href", "style/offline.css");
    // loading style sheet breaks anchors that were jumped to before
    // so force jumping to anchor again
    setTimeout(function() {
        var anchor = location.hash;
        // need to jump to different anchor first (e.g. none)
        location.hash = "#";
        setTimeout(function() {
            location.hash = anchor;
        }, 0);
    }, 0);
  </script>
</head>
<body>
<div class="header" id="qtdocheader">
  <div class="main">
    <div class="main-rounded">
      <div class="navigationbar">
        <table><tr>
<td >Qt 5.12</td><td ><a href="qtgui-index.html">Qt GUI</a></td><td ><a href="qtgui-hellovulkancubes-example.html">Hello Vulkan Cubes Example</a></td><td >renderer.cpp Example File</td></tr></table><table class="buildversion"><tr>
<td id="buildversion" width="100%" align="right"><a href="qtgui-index.html">Qt 5.12.6 Reference Documentation</a></td>
        </tr></table>
      </div>
    </div>
<div class="content">
<div class="line">
<div class="content mainContent">
<div class="sidebar"><div class="sidebar-content" id="sidebar-content"></div></div>
<h1 class="title">renderer.cpp Example File</h1>
<span class="subtitle">hellovulkancubes/renderer.cpp</span>
<!-- $$$hellovulkancubes/renderer.cpp-description -->
<div class="descr"> <a name="details"></a>
<pre class="cpp">

  <span class="comment">/****************************************************************************
  **
  ** 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:
  **
  ** &quot;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
  ** &quot;AS IS&quot; 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.&quot;
  **
  ** $QT_END_LICENSE$
  **
  ****************************************************************************/</span>

  <span class="preprocessor">#include &quot;renderer.h&quot;</span>
  <span class="preprocessor">#include &lt;QVulkanFunctions&gt;</span>
  <span class="preprocessor">#include &lt;QtConcurrentRun&gt;</span>
  <span class="preprocessor">#include &lt;QTime&gt;</span>

  <span class="keyword">static</span> <span class="type">float</span> quadVert<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> { <span class="comment">// Y up, front = CW</span>
      <span class="operator">-</span><span class="number">1</span><span class="operator">,</span> <span class="operator">-</span><span class="number">1</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span>
      <span class="operator">-</span><span class="number">1</span><span class="operator">,</span>  <span class="number">1</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span>
       <span class="number">1</span><span class="operator">,</span> <span class="operator">-</span><span class="number">1</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span>
       <span class="number">1</span><span class="operator">,</span>  <span class="number">1</span><span class="operator">,</span> <span class="number">0</span>
  };

  <span class="preprocessor">#define DBG Q_UNLIKELY(m_window-&gt;isDebugEnabled())</span>

  <span class="keyword">const</span> <span class="type">int</span> MAX_INSTANCES <span class="operator">=</span> <span class="number">16384</span>;
  <span class="keyword">const</span> VkDeviceSize PER_INSTANCE_DATA_SIZE <span class="operator">=</span> <span class="number">6</span> <span class="operator">*</span> <span class="keyword">sizeof</span>(<span class="type">float</span>); <span class="comment">// instTranslate, instDiffuseAdjust</span>

  <span class="keyword">static</span> <span class="keyword">inline</span> VkDeviceSize aligned(VkDeviceSize v<span class="operator">,</span> VkDeviceSize byteAlign)
  {
      <span class="keyword">return</span> (v <span class="operator">+</span> byteAlign <span class="operator">-</span> <span class="number">1</span>) <span class="operator">&amp;</span> <span class="operator">~</span>(byteAlign <span class="operator">-</span> <span class="number">1</span>);
  }

  Renderer<span class="operator">::</span>Renderer(VulkanWindow <span class="operator">*</span>w<span class="operator">,</span> <span class="type">int</span> initialCount)
      : m_window(w)<span class="operator">,</span>
        <span class="comment">// Have the light positioned just behind the default camera position, looking forward.</span>
        m_lightPos(<span class="number">0.0f</span><span class="operator">,</span> <span class="number">0.0f</span><span class="operator">,</span> <span class="number">25.0f</span>)<span class="operator">,</span>
        m_cam(QVector3D(<span class="number">0.0f</span><span class="operator">,</span> <span class="number">0.0f</span><span class="operator">,</span> <span class="number">20.0f</span>))<span class="operator">,</span> <span class="comment">// starting camera position</span>
        m_instCount(initialCount)
  {
      qsrand(<span class="type"><a href="../qtcore/qtime.html">QTime</a></span>(<span class="number">0</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="number">0</span>)<span class="operator">.</span>secsTo(<span class="type"><a href="../qtcore/qtime.html">QTime</a></span><span class="operator">::</span>currentTime()));

      m_floorModel<span class="operator">.</span>translate(<span class="number">0</span><span class="operator">,</span> <span class="operator">-</span><span class="number">5</span><span class="operator">,</span> <span class="number">0</span>);
      m_floorModel<span class="operator">.</span>rotate(<span class="operator">-</span><span class="number">90</span><span class="operator">,</span> <span class="number">1</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="number">0</span>);
      m_floorModel<span class="operator">.</span>scale(<span class="number">20</span><span class="operator">,</span> <span class="number">100</span><span class="operator">,</span> <span class="number">1</span>);

      m_blockMesh<span class="operator">.</span>load(<span class="type"><a href="../qtcore/qstring.html#QStringLiteral">QStringLiteral</a></span>(<span class="string">&quot;:/block.buf&quot;</span>));
      m_logoMesh<span class="operator">.</span>load(<span class="type"><a href="../qtcore/qstring.html#QStringLiteral">QStringLiteral</a></span>(<span class="string">&quot;:/qt_logo.buf&quot;</span>));

      <span class="type"><a href="../qtcore/qobject.html">QObject</a></span><span class="operator">::</span>connect(<span class="operator">&amp;</span>m_frameWatcher<span class="operator">,</span> <span class="operator">&amp;</span><span class="type"><a href="../qtcore/qfuturewatcherbase.html">QFutureWatcherBase</a></span><span class="operator">::</span>finished<span class="operator">,</span> <span class="operator">[</span><span class="keyword">this</span><span class="operator">]</span> {
          <span class="keyword">if</span> (m_framePending) {
              m_framePending <span class="operator">=</span> <span class="keyword">false</span>;
              m_window<span class="operator">-</span><span class="operator">&gt;</span>frameReady();
              m_window<span class="operator">-</span><span class="operator">&gt;</span>requestUpdate();
          }
      });
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>preInitResources()
  {
      <span class="keyword">const</span> <span class="type"><a href="../qtcore/qvector.html">QVector</a></span><span class="operator">&lt;</span><span class="type">int</span><span class="operator">&gt;</span> sampleCounts <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>supportedSampleCounts();
      <span class="keyword">if</span> (DBG)
          <a href="../qtcore/qtglobal.html#qDebug">qDebug</a>() <span class="operator">&lt;</span><span class="operator">&lt;</span> <span class="string">&quot;Supported sample counts:&quot;</span> <span class="operator">&lt;</span><span class="operator">&lt;</span> sampleCounts;
      <span class="keyword">if</span> (sampleCounts<span class="operator">.</span>contains(<span class="number">4</span>)) {
          <span class="keyword">if</span> (DBG)
              <a href="../qtcore/qtglobal.html#qDebug">qDebug</a>(<span class="string">&quot;Requesting 4x MSAA&quot;</span>);
          m_window<span class="operator">-</span><span class="operator">&gt;</span>setSampleCount(<span class="number">4</span>);
      }
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>initResources()
  {
      <span class="keyword">if</span> (DBG)
          <a href="../qtcore/qtglobal.html#qDebug">qDebug</a>(<span class="string">&quot;Renderer init&quot;</span>);

      m_animating <span class="operator">=</span> <span class="keyword">true</span>;
      m_framePending <span class="operator">=</span> <span class="keyword">false</span>;

      <span class="type"><a href="qvulkaninstance.html">QVulkanInstance</a></span> <span class="operator">*</span>inst <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>vulkanInstance();
      VkDevice dev <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>device();
      <span class="keyword">const</span> VkPhysicalDeviceLimits <span class="operator">*</span>pdevLimits <span class="operator">=</span> <span class="operator">&amp;</span>m_window<span class="operator">-</span><span class="operator">&gt;</span>physicalDeviceProperties()<span class="operator">-</span><span class="operator">&gt;</span>limits;
      <span class="keyword">const</span> VkDeviceSize uniAlign <span class="operator">=</span> pdevLimits<span class="operator">-</span><span class="operator">&gt;</span>minUniformBufferOffsetAlignment;

      m_devFuncs <span class="operator">=</span> inst<span class="operator">-</span><span class="operator">&gt;</span>deviceFunctions(dev);

      <span class="comment">// Note the std140 packing rules. A vec3 still has an alignment of 16,</span>
      <span class="comment">// while a mat3 is like 3 * vec3.</span>
      m_itemMaterial<span class="operator">.</span>vertUniSize <span class="operator">=</span> aligned(<span class="number">2</span> <span class="operator">*</span> <span class="number">64</span> <span class="operator">+</span> <span class="number">48</span><span class="operator">,</span> uniAlign); <span class="comment">// see color_phong.vert</span>
      m_itemMaterial<span class="operator">.</span>fragUniSize <span class="operator">=</span> aligned(<span class="number">6</span> <span class="operator">*</span> <span class="number">16</span> <span class="operator">+</span> <span class="number">12</span> <span class="operator">+</span> <span class="number">2</span> <span class="operator">*</span> <span class="number">4</span><span class="operator">,</span> uniAlign); <span class="comment">// see color_phong.frag</span>

      <span class="keyword">if</span> (<span class="operator">!</span>m_itemMaterial<span class="operator">.</span>vs<span class="operator">.</span>isValid())
          m_itemMaterial<span class="operator">.</span>vs<span class="operator">.</span>load(inst<span class="operator">,</span> dev<span class="operator">,</span> <span class="type"><a href="../qtcore/qstring.html#QStringLiteral">QStringLiteral</a></span>(<span class="string">&quot;:/color_phong_vert.spv&quot;</span>));
      <span class="keyword">if</span> (<span class="operator">!</span>m_itemMaterial<span class="operator">.</span>fs<span class="operator">.</span>isValid())
          m_itemMaterial<span class="operator">.</span>fs<span class="operator">.</span>load(inst<span class="operator">,</span> dev<span class="operator">,</span> <span class="type"><a href="../qtcore/qstring.html#QStringLiteral">QStringLiteral</a></span>(<span class="string">&quot;:/color_phong_frag.spv&quot;</span>));

      <span class="keyword">if</span> (<span class="operator">!</span>m_floorMaterial<span class="operator">.</span>vs<span class="operator">.</span>isValid())
          m_floorMaterial<span class="operator">.</span>vs<span class="operator">.</span>load(inst<span class="operator">,</span> dev<span class="operator">,</span> <span class="type"><a href="../qtcore/qstring.html#QStringLiteral">QStringLiteral</a></span>(<span class="string">&quot;:/color_vert.spv&quot;</span>));
      <span class="keyword">if</span> (<span class="operator">!</span>m_floorMaterial<span class="operator">.</span>fs<span class="operator">.</span>isValid())
          m_floorMaterial<span class="operator">.</span>fs<span class="operator">.</span>load(inst<span class="operator">,</span> dev<span class="operator">,</span> <span class="type"><a href="../qtcore/qstring.html#QStringLiteral">QStringLiteral</a></span>(<span class="string">&quot;:/color_frag.spv&quot;</span>));

      m_pipelinesFuture <span class="operator">=</span> <span class="type">QtConcurrent</span><span class="operator">::</span>run(<span class="keyword">this</span><span class="operator">,</span> <span class="operator">&amp;</span>Renderer<span class="operator">::</span>createPipelines);
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>createPipelines()
  {
      VkDevice dev <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>device();

      VkPipelineCacheCreateInfo pipelineCacheInfo;
      memset(<span class="operator">&amp;</span>pipelineCacheInfo<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(pipelineCacheInfo));
      pipelineCacheInfo<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
      VkResult err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCreatePipelineCache(dev<span class="operator">,</span> <span class="operator">&amp;</span>pipelineCacheInfo<span class="operator">,</span> nullptr<span class="operator">,</span> <span class="operator">&amp;</span>m_pipelineCache);
      <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
          <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to create pipeline cache: %d&quot;</span><span class="operator">,</span> err);

      createItemPipeline();
      createFloorPipeline();
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>createItemPipeline()
  {
      VkDevice dev <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>device();

      <span class="comment">// Vertex layout.</span>
      VkVertexInputBindingDescription vertexBindingDesc<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> {
          {
              <span class="number">0</span><span class="operator">,</span> <span class="comment">// binding</span>
              <span class="number">8</span> <span class="operator">*</span> <span class="keyword">sizeof</span>(<span class="type">float</span>)<span class="operator">,</span>
              VK_VERTEX_INPUT_RATE_VERTEX
          }<span class="operator">,</span>
          {
              <span class="number">1</span><span class="operator">,</span>
              <span class="number">6</span> <span class="operator">*</span> <span class="keyword">sizeof</span>(<span class="type">float</span>)<span class="operator">,</span>
              VK_VERTEX_INPUT_RATE_INSTANCE
          }
      };
      VkVertexInputAttributeDescription vertexAttrDesc<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> {
          { <span class="comment">// position</span>
              <span class="number">0</span><span class="operator">,</span> <span class="comment">// location</span>
              <span class="number">0</span><span class="operator">,</span> <span class="comment">// binding</span>
              VK_FORMAT_R32G32B32_SFLOAT<span class="operator">,</span>
              <span class="number">0</span> <span class="comment">// offset</span>
          }<span class="operator">,</span>
          { <span class="comment">// normal</span>
              <span class="number">1</span><span class="operator">,</span>
              <span class="number">0</span><span class="operator">,</span>
              VK_FORMAT_R32G32B32_SFLOAT<span class="operator">,</span>
              <span class="number">5</span> <span class="operator">*</span> <span class="keyword">sizeof</span>(<span class="type">float</span>)
          }<span class="operator">,</span>
          { <span class="comment">// instTranslate</span>
              <span class="number">2</span><span class="operator">,</span>
              <span class="number">1</span><span class="operator">,</span>
              VK_FORMAT_R32G32B32_SFLOAT<span class="operator">,</span>
              <span class="number">0</span>
          }<span class="operator">,</span>
          { <span class="comment">// instDiffuseAdjust</span>
              <span class="number">3</span><span class="operator">,</span>
              <span class="number">1</span><span class="operator">,</span>
              VK_FORMAT_R32G32B32_SFLOAT<span class="operator">,</span>
              <span class="number">3</span> <span class="operator">*</span> <span class="keyword">sizeof</span>(<span class="type">float</span>)
          }
      };

      VkPipelineVertexInputStateCreateInfo vertexInputInfo;
      vertexInputInfo<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
      vertexInputInfo<span class="operator">.</span>pNext <span class="operator">=</span> nullptr;
      vertexInputInfo<span class="operator">.</span>flags <span class="operator">=</span> <span class="number">0</span>;
      vertexInputInfo<span class="operator">.</span>vertexBindingDescriptionCount <span class="operator">=</span> <span class="keyword">sizeof</span>(vertexBindingDesc) <span class="operator">/</span> <span class="keyword">sizeof</span>(vertexBindingDesc<span class="operator">[</span><span class="number">0</span><span class="operator">]</span>);
      vertexInputInfo<span class="operator">.</span>pVertexBindingDescriptions <span class="operator">=</span> vertexBindingDesc;
      vertexInputInfo<span class="operator">.</span>vertexAttributeDescriptionCount <span class="operator">=</span> <span class="keyword">sizeof</span>(vertexAttrDesc) <span class="operator">/</span> <span class="keyword">sizeof</span>(vertexAttrDesc<span class="operator">[</span><span class="number">0</span><span class="operator">]</span>);
      vertexInputInfo<span class="operator">.</span>pVertexAttributeDescriptions <span class="operator">=</span> vertexAttrDesc;

      <span class="comment">// Descriptor set layout.</span>
      VkDescriptorPoolSize descPoolSizes<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> {
          { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC<span class="operator">,</span> <span class="number">2</span> }
      };
      VkDescriptorPoolCreateInfo descPoolInfo;
      memset(<span class="operator">&amp;</span>descPoolInfo<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(descPoolInfo));
      descPoolInfo<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
      descPoolInfo<span class="operator">.</span>maxSets <span class="operator">=</span> <span class="number">1</span>; <span class="comment">// a single set is enough due to the dynamic uniform buffer</span>
      descPoolInfo<span class="operator">.</span>poolSizeCount <span class="operator">=</span> <span class="keyword">sizeof</span>(descPoolSizes) <span class="operator">/</span> <span class="keyword">sizeof</span>(descPoolSizes<span class="operator">[</span><span class="number">0</span><span class="operator">]</span>);
      descPoolInfo<span class="operator">.</span>pPoolSizes <span class="operator">=</span> descPoolSizes;
      VkResult err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCreateDescriptorPool(dev<span class="operator">,</span> <span class="operator">&amp;</span>descPoolInfo<span class="operator">,</span> nullptr<span class="operator">,</span> <span class="operator">&amp;</span>m_itemMaterial<span class="operator">.</span>descPool);
      <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
          <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to create descriptor pool: %d&quot;</span><span class="operator">,</span> err);

      VkDescriptorSetLayoutBinding layoutBindings<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span>
      {
          {
              <span class="number">0</span><span class="operator">,</span> <span class="comment">// binding</span>
              VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC<span class="operator">,</span>
              <span class="number">1</span><span class="operator">,</span> <span class="comment">// descriptorCount</span>
              VK_SHADER_STAGE_VERTEX_BIT<span class="operator">,</span>
              nullptr
          }<span class="operator">,</span>
          {
              <span class="number">1</span><span class="operator">,</span>
              VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC<span class="operator">,</span>
              <span class="number">1</span><span class="operator">,</span>
              VK_SHADER_STAGE_FRAGMENT_BIT<span class="operator">,</span>
              nullptr
          }
      };
      VkDescriptorSetLayoutCreateInfo descLayoutInfo <span class="operator">=</span> {
          VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO<span class="operator">,</span>
          nullptr<span class="operator">,</span>
          <span class="number">0</span><span class="operator">,</span>
          <span class="keyword">sizeof</span>(layoutBindings) <span class="operator">/</span> <span class="keyword">sizeof</span>(layoutBindings<span class="operator">[</span><span class="number">0</span><span class="operator">]</span>)<span class="operator">,</span>
          layoutBindings
      };
      err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCreateDescriptorSetLayout(dev<span class="operator">,</span> <span class="operator">&amp;</span>descLayoutInfo<span class="operator">,</span> nullptr<span class="operator">,</span> <span class="operator">&amp;</span>m_itemMaterial<span class="operator">.</span>descSetLayout);
      <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
          <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to create descriptor set layout: %d&quot;</span><span class="operator">,</span> err);

      VkDescriptorSetAllocateInfo descSetAllocInfo <span class="operator">=</span> {
          VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO<span class="operator">,</span>
          nullptr<span class="operator">,</span>
          m_itemMaterial<span class="operator">.</span>descPool<span class="operator">,</span>
          <span class="number">1</span><span class="operator">,</span>
          <span class="operator">&amp;</span>m_itemMaterial<span class="operator">.</span>descSetLayout
      };
      err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkAllocateDescriptorSets(dev<span class="operator">,</span> <span class="operator">&amp;</span>descSetAllocInfo<span class="operator">,</span> <span class="operator">&amp;</span>m_itemMaterial<span class="operator">.</span>descSet);
      <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
          <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to allocate descriptor set: %d&quot;</span><span class="operator">,</span> err);

      <span class="comment">// Graphics pipeline.</span>
      VkPipelineLayoutCreateInfo pipelineLayoutInfo;
      memset(<span class="operator">&amp;</span>pipelineLayoutInfo<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(pipelineLayoutInfo));
      pipelineLayoutInfo<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
      pipelineLayoutInfo<span class="operator">.</span>setLayoutCount <span class="operator">=</span> <span class="number">1</span>;
      pipelineLayoutInfo<span class="operator">.</span>pSetLayouts <span class="operator">=</span> <span class="operator">&amp;</span>m_itemMaterial<span class="operator">.</span>descSetLayout;

      err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCreatePipelineLayout(dev<span class="operator">,</span> <span class="operator">&amp;</span>pipelineLayoutInfo<span class="operator">,</span> nullptr<span class="operator">,</span> <span class="operator">&amp;</span>m_itemMaterial<span class="operator">.</span>pipelineLayout);
      <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
          <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to create pipeline layout: %d&quot;</span><span class="operator">,</span> err);

      VkGraphicsPipelineCreateInfo pipelineInfo;
      memset(<span class="operator">&amp;</span>pipelineInfo<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(pipelineInfo));
      pipelineInfo<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;

      VkPipelineShaderStageCreateInfo shaderStages<span class="operator">[</span><span class="number">2</span><span class="operator">]</span> <span class="operator">=</span> {
          {
              VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO<span class="operator">,</span>
              nullptr<span class="operator">,</span>
              <span class="number">0</span><span class="operator">,</span>
              VK_SHADER_STAGE_VERTEX_BIT<span class="operator">,</span>
              m_itemMaterial<span class="operator">.</span>vs<span class="operator">.</span>data()<span class="operator">-</span><span class="operator">&gt;</span>shaderModule<span class="operator">,</span>
              <span class="string">&quot;main&quot;</span><span class="operator">,</span>
              nullptr
          }<span class="operator">,</span>
          {
              VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO<span class="operator">,</span>
              nullptr<span class="operator">,</span>
              <span class="number">0</span><span class="operator">,</span>
              VK_SHADER_STAGE_FRAGMENT_BIT<span class="operator">,</span>
              m_itemMaterial<span class="operator">.</span>fs<span class="operator">.</span>data()<span class="operator">-</span><span class="operator">&gt;</span>shaderModule<span class="operator">,</span>
              <span class="string">&quot;main&quot;</span><span class="operator">,</span>
              nullptr
          }
      };
      pipelineInfo<span class="operator">.</span>stageCount <span class="operator">=</span> <span class="number">2</span>;
      pipelineInfo<span class="operator">.</span>pStages <span class="operator">=</span> shaderStages;

      pipelineInfo<span class="operator">.</span>pVertexInputState <span class="operator">=</span> <span class="operator">&amp;</span>vertexInputInfo;

      VkPipelineInputAssemblyStateCreateInfo ia;
      memset(<span class="operator">&amp;</span>ia<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(ia));
      ia<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
      ia<span class="operator">.</span>topology <span class="operator">=</span> VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
      pipelineInfo<span class="operator">.</span>pInputAssemblyState <span class="operator">=</span> <span class="operator">&amp;</span>ia;

      VkPipelineViewportStateCreateInfo vp;
      memset(<span class="operator">&amp;</span>vp<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(vp));
      vp<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
      vp<span class="operator">.</span>viewportCount <span class="operator">=</span> <span class="number">1</span>;
      vp<span class="operator">.</span>scissorCount <span class="operator">=</span> <span class="number">1</span>;
      pipelineInfo<span class="operator">.</span>pViewportState <span class="operator">=</span> <span class="operator">&amp;</span>vp;

      VkPipelineRasterizationStateCreateInfo rs;
      memset(<span class="operator">&amp;</span>rs<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(rs));
      rs<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
      rs<span class="operator">.</span>polygonMode <span class="operator">=</span> VK_POLYGON_MODE_FILL;
      rs<span class="operator">.</span>cullMode <span class="operator">=</span> VK_CULL_MODE_BACK_BIT;
      rs<span class="operator">.</span>frontFace <span class="operator">=</span> VK_FRONT_FACE_COUNTER_CLOCKWISE;
      rs<span class="operator">.</span>lineWidth <span class="operator">=</span> <span class="number">1.0f</span>;
      pipelineInfo<span class="operator">.</span>pRasterizationState <span class="operator">=</span> <span class="operator">&amp;</span>rs;

      VkPipelineMultisampleStateCreateInfo ms;
      memset(<span class="operator">&amp;</span>ms<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(ms));
      ms<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
      ms<span class="operator">.</span>rasterizationSamples <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>sampleCountFlagBits();
      pipelineInfo<span class="operator">.</span>pMultisampleState <span class="operator">=</span> <span class="operator">&amp;</span>ms;

      VkPipelineDepthStencilStateCreateInfo ds;
      memset(<span class="operator">&amp;</span>ds<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(ds));
      ds<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
      ds<span class="operator">.</span>depthTestEnable <span class="operator">=</span> VK_TRUE;
      ds<span class="operator">.</span>depthWriteEnable <span class="operator">=</span> VK_TRUE;
      ds<span class="operator">.</span>depthCompareOp <span class="operator">=</span> VK_COMPARE_OP_LESS_OR_EQUAL;
      pipelineInfo<span class="operator">.</span>pDepthStencilState <span class="operator">=</span> <span class="operator">&amp;</span>ds;

      VkPipelineColorBlendStateCreateInfo cb;
      memset(<span class="operator">&amp;</span>cb<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(cb));
      cb<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
      VkPipelineColorBlendAttachmentState att;
      memset(<span class="operator">&amp;</span>att<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(att));
      att<span class="operator">.</span>colorWriteMask <span class="operator">=</span> <span class="number">0xF</span>;
      cb<span class="operator">.</span>attachmentCount <span class="operator">=</span> <span class="number">1</span>;
      cb<span class="operator">.</span>pAttachments <span class="operator">=</span> <span class="operator">&amp;</span>att;
      pipelineInfo<span class="operator">.</span>pColorBlendState <span class="operator">=</span> <span class="operator">&amp;</span>cb;

      VkDynamicState dynEnable<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> { VK_DYNAMIC_STATE_VIEWPORT<span class="operator">,</span> VK_DYNAMIC_STATE_SCISSOR };
      VkPipelineDynamicStateCreateInfo dyn;
      memset(<span class="operator">&amp;</span>dyn<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(dyn));
      dyn<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
      dyn<span class="operator">.</span>dynamicStateCount <span class="operator">=</span> <span class="keyword">sizeof</span>(dynEnable) <span class="operator">/</span> <span class="keyword">sizeof</span>(VkDynamicState);
      dyn<span class="operator">.</span>pDynamicStates <span class="operator">=</span> dynEnable;
      pipelineInfo<span class="operator">.</span>pDynamicState <span class="operator">=</span> <span class="operator">&amp;</span>dyn;

      pipelineInfo<span class="operator">.</span>layout <span class="operator">=</span> m_itemMaterial<span class="operator">.</span>pipelineLayout;
      pipelineInfo<span class="operator">.</span>renderPass <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>defaultRenderPass();

      err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCreateGraphicsPipelines(dev<span class="operator">,</span> m_pipelineCache<span class="operator">,</span> <span class="number">1</span><span class="operator">,</span> <span class="operator">&amp;</span>pipelineInfo<span class="operator">,</span> nullptr<span class="operator">,</span> <span class="operator">&amp;</span>m_itemMaterial<span class="operator">.</span>pipeline);
      <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
          <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to create graphics pipeline: %d&quot;</span><span class="operator">,</span> err);
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>createFloorPipeline()
  {
      VkDevice dev <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>device();

      <span class="comment">// Vertex layout.</span>
      VkVertexInputBindingDescription vertexBindingDesc <span class="operator">=</span> {
          <span class="number">0</span><span class="operator">,</span> <span class="comment">// binding</span>
          <span class="number">3</span> <span class="operator">*</span> <span class="keyword">sizeof</span>(<span class="type">float</span>)<span class="operator">,</span>
          VK_VERTEX_INPUT_RATE_VERTEX
      };
      VkVertexInputAttributeDescription vertexAttrDesc<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> {
          { <span class="comment">// position</span>
              <span class="number">0</span><span class="operator">,</span> <span class="comment">// location</span>
              <span class="number">0</span><span class="operator">,</span> <span class="comment">// binding</span>
              VK_FORMAT_R32G32B32_SFLOAT<span class="operator">,</span>
              <span class="number">0</span> <span class="comment">// offset</span>
          }<span class="operator">,</span>
      };

      VkPipelineVertexInputStateCreateInfo vertexInputInfo;
      vertexInputInfo<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
      vertexInputInfo<span class="operator">.</span>pNext <span class="operator">=</span> nullptr;
      vertexInputInfo<span class="operator">.</span>flags <span class="operator">=</span> <span class="number">0</span>;
      vertexInputInfo<span class="operator">.</span>vertexBindingDescriptionCount <span class="operator">=</span> <span class="number">1</span>;
      vertexInputInfo<span class="operator">.</span>pVertexBindingDescriptions <span class="operator">=</span> <span class="operator">&amp;</span>vertexBindingDesc;
      vertexInputInfo<span class="operator">.</span>vertexAttributeDescriptionCount <span class="operator">=</span> <span class="keyword">sizeof</span>(vertexAttrDesc) <span class="operator">/</span> <span class="keyword">sizeof</span>(vertexAttrDesc<span class="operator">[</span><span class="number">0</span><span class="operator">]</span>);
      vertexInputInfo<span class="operator">.</span>pVertexAttributeDescriptions <span class="operator">=</span> vertexAttrDesc;

      <span class="comment">// Do not bother with uniform buffers and descriptors, all the data fits</span>
      <span class="comment">// into the spec mandated minimum of 128 bytes for push constants.</span>
      VkPushConstantRange pcr<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> {
          <span class="comment">// mvp</span>
          {
              VK_SHADER_STAGE_VERTEX_BIT<span class="operator">,</span>
              <span class="number">0</span><span class="operator">,</span>
              <span class="number">64</span>
          }<span class="operator">,</span>
          <span class="comment">// color</span>
          {
              VK_SHADER_STAGE_FRAGMENT_BIT<span class="operator">,</span>
              <span class="number">64</span><span class="operator">,</span>
              <span class="number">12</span>
          }
      };

      VkPipelineLayoutCreateInfo pipelineLayoutInfo;
      memset(<span class="operator">&amp;</span>pipelineLayoutInfo<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(pipelineLayoutInfo));
      pipelineLayoutInfo<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
      pipelineLayoutInfo<span class="operator">.</span>pushConstantRangeCount <span class="operator">=</span> <span class="keyword">sizeof</span>(pcr) <span class="operator">/</span> <span class="keyword">sizeof</span>(pcr<span class="operator">[</span><span class="number">0</span><span class="operator">]</span>);
      pipelineLayoutInfo<span class="operator">.</span>pPushConstantRanges <span class="operator">=</span> pcr;

      VkResult err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCreatePipelineLayout(dev<span class="operator">,</span> <span class="operator">&amp;</span>pipelineLayoutInfo<span class="operator">,</span> nullptr<span class="operator">,</span> <span class="operator">&amp;</span>m_floorMaterial<span class="operator">.</span>pipelineLayout);
      <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
          <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to create pipeline layout: %d&quot;</span><span class="operator">,</span> err);

      VkGraphicsPipelineCreateInfo pipelineInfo;
      memset(<span class="operator">&amp;</span>pipelineInfo<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(pipelineInfo));
      pipelineInfo<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;

      VkPipelineShaderStageCreateInfo shaderStages<span class="operator">[</span><span class="number">2</span><span class="operator">]</span> <span class="operator">=</span> {
          {
              VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO<span class="operator">,</span>
              nullptr<span class="operator">,</span>
              <span class="number">0</span><span class="operator">,</span>
              VK_SHADER_STAGE_VERTEX_BIT<span class="operator">,</span>
              m_floorMaterial<span class="operator">.</span>vs<span class="operator">.</span>data()<span class="operator">-</span><span class="operator">&gt;</span>shaderModule<span class="operator">,</span>
              <span class="string">&quot;main&quot;</span><span class="operator">,</span>
              nullptr
          }<span class="operator">,</span>
          {
              VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO<span class="operator">,</span>
              nullptr<span class="operator">,</span>
              <span class="number">0</span><span class="operator">,</span>
              VK_SHADER_STAGE_FRAGMENT_BIT<span class="operator">,</span>
              m_floorMaterial<span class="operator">.</span>fs<span class="operator">.</span>data()<span class="operator">-</span><span class="operator">&gt;</span>shaderModule<span class="operator">,</span>
              <span class="string">&quot;main&quot;</span><span class="operator">,</span>
              nullptr
          }
      };
      pipelineInfo<span class="operator">.</span>stageCount <span class="operator">=</span> <span class="number">2</span>;
      pipelineInfo<span class="operator">.</span>pStages <span class="operator">=</span> shaderStages;

      pipelineInfo<span class="operator">.</span>pVertexInputState <span class="operator">=</span> <span class="operator">&amp;</span>vertexInputInfo;

      VkPipelineInputAssemblyStateCreateInfo ia;
      memset(<span class="operator">&amp;</span>ia<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(ia));
      ia<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
      ia<span class="operator">.</span>topology <span class="operator">=</span> VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
      pipelineInfo<span class="operator">.</span>pInputAssemblyState <span class="operator">=</span> <span class="operator">&amp;</span>ia;

      VkPipelineViewportStateCreateInfo vp;
      memset(<span class="operator">&amp;</span>vp<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(vp));
      vp<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
      vp<span class="operator">.</span>viewportCount <span class="operator">=</span> <span class="number">1</span>;
      vp<span class="operator">.</span>scissorCount <span class="operator">=</span> <span class="number">1</span>;
      pipelineInfo<span class="operator">.</span>pViewportState <span class="operator">=</span> <span class="operator">&amp;</span>vp;

      VkPipelineRasterizationStateCreateInfo rs;
      memset(<span class="operator">&amp;</span>rs<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(rs));
      rs<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
      rs<span class="operator">.</span>polygonMode <span class="operator">=</span> VK_POLYGON_MODE_FILL;
      rs<span class="operator">.</span>cullMode <span class="operator">=</span> VK_CULL_MODE_BACK_BIT;
      rs<span class="operator">.</span>frontFace <span class="operator">=</span> VK_FRONT_FACE_CLOCKWISE;
      rs<span class="operator">.</span>lineWidth <span class="operator">=</span> <span class="number">1.0f</span>;
      pipelineInfo<span class="operator">.</span>pRasterizationState <span class="operator">=</span> <span class="operator">&amp;</span>rs;

      VkPipelineMultisampleStateCreateInfo ms;
      memset(<span class="operator">&amp;</span>ms<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(ms));
      ms<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
      ms<span class="operator">.</span>rasterizationSamples <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>sampleCountFlagBits();
      pipelineInfo<span class="operator">.</span>pMultisampleState <span class="operator">=</span> <span class="operator">&amp;</span>ms;

      VkPipelineDepthStencilStateCreateInfo ds;
      memset(<span class="operator">&amp;</span>ds<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(ds));
      ds<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
      ds<span class="operator">.</span>depthTestEnable <span class="operator">=</span> VK_TRUE;
      ds<span class="operator">.</span>depthWriteEnable <span class="operator">=</span> VK_TRUE;
      ds<span class="operator">.</span>depthCompareOp <span class="operator">=</span> VK_COMPARE_OP_LESS_OR_EQUAL;
      pipelineInfo<span class="operator">.</span>pDepthStencilState <span class="operator">=</span> <span class="operator">&amp;</span>ds;

      VkPipelineColorBlendStateCreateInfo cb;
      memset(<span class="operator">&amp;</span>cb<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(cb));
      cb<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
      VkPipelineColorBlendAttachmentState att;
      memset(<span class="operator">&amp;</span>att<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(att));
      att<span class="operator">.</span>colorWriteMask <span class="operator">=</span> <span class="number">0xF</span>;
      cb<span class="operator">.</span>attachmentCount <span class="operator">=</span> <span class="number">1</span>;
      cb<span class="operator">.</span>pAttachments <span class="operator">=</span> <span class="operator">&amp;</span>att;
      pipelineInfo<span class="operator">.</span>pColorBlendState <span class="operator">=</span> <span class="operator">&amp;</span>cb;

      VkDynamicState dynEnable<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> { VK_DYNAMIC_STATE_VIEWPORT<span class="operator">,</span> VK_DYNAMIC_STATE_SCISSOR };
      VkPipelineDynamicStateCreateInfo dyn;
      memset(<span class="operator">&amp;</span>dyn<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(dyn));
      dyn<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
      dyn<span class="operator">.</span>dynamicStateCount <span class="operator">=</span> <span class="keyword">sizeof</span>(dynEnable) <span class="operator">/</span> <span class="keyword">sizeof</span>(VkDynamicState);
      dyn<span class="operator">.</span>pDynamicStates <span class="operator">=</span> dynEnable;
      pipelineInfo<span class="operator">.</span>pDynamicState <span class="operator">=</span> <span class="operator">&amp;</span>dyn;

      pipelineInfo<span class="operator">.</span>layout <span class="operator">=</span> m_floorMaterial<span class="operator">.</span>pipelineLayout;
      pipelineInfo<span class="operator">.</span>renderPass <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>defaultRenderPass();

      err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCreateGraphicsPipelines(dev<span class="operator">,</span> m_pipelineCache<span class="operator">,</span> <span class="number">1</span><span class="operator">,</span> <span class="operator">&amp;</span>pipelineInfo<span class="operator">,</span> nullptr<span class="operator">,</span> <span class="operator">&amp;</span>m_floorMaterial<span class="operator">.</span>pipeline);
      <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
          <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to create graphics pipeline: %d&quot;</span><span class="operator">,</span> err);
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>initSwapChainResources()
  {
      m_proj <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>clipCorrectionMatrix();
      <span class="keyword">const</span> <span class="type"><a href="../qtcore/qsize.html">QSize</a></span> sz <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>swapChainImageSize();
      m_proj<span class="operator">.</span>perspective(<span class="number">45.0f</span><span class="operator">,</span> sz<span class="operator">.</span>width() <span class="operator">/</span> (<span class="type">float</span>) sz<span class="operator">.</span>height()<span class="operator">,</span> <span class="number">0.01f</span><span class="operator">,</span> <span class="number">1000.0f</span>);
      markViewProjDirty();
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>releaseSwapChainResources()
  {
      <span class="comment">// It is important to finish the pending frame right here since this is the</span>
      <span class="comment">// last opportunity to act with all resources intact.</span>
      m_frameWatcher<span class="operator">.</span>waitForFinished();
      <span class="comment">// Cannot count on the finished() signal being emitted before returning</span>
      <span class="comment">// from here.</span>
      <span class="keyword">if</span> (m_framePending) {
          m_framePending <span class="operator">=</span> <span class="keyword">false</span>;
          m_window<span class="operator">-</span><span class="operator">&gt;</span>frameReady();
      }
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>releaseResources()
  {
      <span class="keyword">if</span> (DBG)
          <a href="../qtcore/qtglobal.html#qDebug">qDebug</a>(<span class="string">&quot;Renderer release&quot;</span>);

      m_pipelinesFuture<span class="operator">.</span>waitForFinished();

      VkDevice dev <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>device();

      <span class="keyword">if</span> (m_itemMaterial<span class="operator">.</span>descSetLayout) {
          m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkDestroyDescriptorSetLayout(dev<span class="operator">,</span> m_itemMaterial<span class="operator">.</span>descSetLayout<span class="operator">,</span> nullptr);
          m_itemMaterial<span class="operator">.</span>descSetLayout <span class="operator">=</span> VK_NULL_HANDLE;
      }

      <span class="keyword">if</span> (m_itemMaterial<span class="operator">.</span>descPool) {
          m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkDestroyDescriptorPool(dev<span class="operator">,</span> m_itemMaterial<span class="operator">.</span>descPool<span class="operator">,</span> nullptr);
          m_itemMaterial<span class="operator">.</span>descPool <span class="operator">=</span> VK_NULL_HANDLE;
      }

      <span class="keyword">if</span> (m_itemMaterial<span class="operator">.</span>pipeline) {
          m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkDestroyPipeline(dev<span class="operator">,</span> m_itemMaterial<span class="operator">.</span>pipeline<span class="operator">,</span> nullptr);
          m_itemMaterial<span class="operator">.</span>pipeline <span class="operator">=</span> VK_NULL_HANDLE;
      }

      <span class="keyword">if</span> (m_itemMaterial<span class="operator">.</span>pipelineLayout) {
          m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkDestroyPipelineLayout(dev<span class="operator">,</span> m_itemMaterial<span class="operator">.</span>pipelineLayout<span class="operator">,</span> nullptr);
          m_itemMaterial<span class="operator">.</span>pipelineLayout <span class="operator">=</span> VK_NULL_HANDLE;
      }

      <span class="keyword">if</span> (m_floorMaterial<span class="operator">.</span>pipeline) {
          m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkDestroyPipeline(dev<span class="operator">,</span> m_floorMaterial<span class="operator">.</span>pipeline<span class="operator">,</span> nullptr);
          m_floorMaterial<span class="operator">.</span>pipeline <span class="operator">=</span> VK_NULL_HANDLE;
      }

      <span class="keyword">if</span> (m_floorMaterial<span class="operator">.</span>pipelineLayout) {
          m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkDestroyPipelineLayout(dev<span class="operator">,</span> m_floorMaterial<span class="operator">.</span>pipelineLayout<span class="operator">,</span> nullptr);
          m_floorMaterial<span class="operator">.</span>pipelineLayout <span class="operator">=</span> VK_NULL_HANDLE;
      }

      <span class="keyword">if</span> (m_pipelineCache) {
          m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkDestroyPipelineCache(dev<span class="operator">,</span> m_pipelineCache<span class="operator">,</span> nullptr);
          m_pipelineCache <span class="operator">=</span> VK_NULL_HANDLE;
      }

      <span class="keyword">if</span> (m_blockVertexBuf) {
          m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkDestroyBuffer(dev<span class="operator">,</span> m_blockVertexBuf<span class="operator">,</span> nullptr);
          m_blockVertexBuf <span class="operator">=</span> VK_NULL_HANDLE;
      }

      <span class="keyword">if</span> (m_logoVertexBuf) {
          m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkDestroyBuffer(dev<span class="operator">,</span> m_logoVertexBuf<span class="operator">,</span> nullptr);
          m_logoVertexBuf <span class="operator">=</span> VK_NULL_HANDLE;
      }

      <span class="keyword">if</span> (m_floorVertexBuf) {
          m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkDestroyBuffer(dev<span class="operator">,</span> m_floorVertexBuf<span class="operator">,</span> nullptr);
          m_floorVertexBuf <span class="operator">=</span> VK_NULL_HANDLE;
      }

      <span class="keyword">if</span> (m_uniBuf) {
          m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkDestroyBuffer(dev<span class="operator">,</span> m_uniBuf<span class="operator">,</span> nullptr);
          m_uniBuf <span class="operator">=</span> VK_NULL_HANDLE;
      }

      <span class="keyword">if</span> (m_bufMem) {
          m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkFreeMemory(dev<span class="operator">,</span> m_bufMem<span class="operator">,</span> nullptr);
          m_bufMem <span class="operator">=</span> VK_NULL_HANDLE;
      }

      <span class="keyword">if</span> (m_instBuf) {
          m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkDestroyBuffer(dev<span class="operator">,</span> m_instBuf<span class="operator">,</span> nullptr);
          m_instBuf <span class="operator">=</span> VK_NULL_HANDLE;
      }

      <span class="keyword">if</span> (m_instBufMem) {
          m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkFreeMemory(dev<span class="operator">,</span> m_instBufMem<span class="operator">,</span> nullptr);
          m_instBufMem <span class="operator">=</span> VK_NULL_HANDLE;
      }

      <span class="keyword">if</span> (m_itemMaterial<span class="operator">.</span>vs<span class="operator">.</span>isValid()) {
          m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkDestroyShaderModule(dev<span class="operator">,</span> m_itemMaterial<span class="operator">.</span>vs<span class="operator">.</span>data()<span class="operator">-</span><span class="operator">&gt;</span>shaderModule<span class="operator">,</span> nullptr);
          m_itemMaterial<span class="operator">.</span>vs<span class="operator">.</span>reset();
      }
      <span class="keyword">if</span> (m_itemMaterial<span class="operator">.</span>fs<span class="operator">.</span>isValid()) {
          m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkDestroyShaderModule(dev<span class="operator">,</span> m_itemMaterial<span class="operator">.</span>fs<span class="operator">.</span>data()<span class="operator">-</span><span class="operator">&gt;</span>shaderModule<span class="operator">,</span> nullptr);
          m_itemMaterial<span class="operator">.</span>fs<span class="operator">.</span>reset();
      }

      <span class="keyword">if</span> (m_floorMaterial<span class="operator">.</span>vs<span class="operator">.</span>isValid()) {
          m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkDestroyShaderModule(dev<span class="operator">,</span> m_floorMaterial<span class="operator">.</span>vs<span class="operator">.</span>data()<span class="operator">-</span><span class="operator">&gt;</span>shaderModule<span class="operator">,</span> nullptr);
          m_floorMaterial<span class="operator">.</span>vs<span class="operator">.</span>reset();
      }
      <span class="keyword">if</span> (m_floorMaterial<span class="operator">.</span>fs<span class="operator">.</span>isValid()) {
          m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkDestroyShaderModule(dev<span class="operator">,</span> m_floorMaterial<span class="operator">.</span>fs<span class="operator">.</span>data()<span class="operator">-</span><span class="operator">&gt;</span>shaderModule<span class="operator">,</span> nullptr);
          m_floorMaterial<span class="operator">.</span>fs<span class="operator">.</span>reset();
      }
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>ensureBuffers()
  {
      <span class="keyword">if</span> (m_blockVertexBuf)
          <span class="keyword">return</span>;

      VkDevice dev <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>device();
      <span class="keyword">const</span> <span class="type">int</span> concurrentFrameCount <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>concurrentFrameCount();

      <span class="comment">// Vertex buffer for the block.</span>
      VkBufferCreateInfo bufInfo;
      memset(<span class="operator">&amp;</span>bufInfo<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(bufInfo));
      bufInfo<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
      <span class="keyword">const</span> <span class="type">int</span> blockMeshByteCount <span class="operator">=</span> m_blockMesh<span class="operator">.</span>data()<span class="operator">-</span><span class="operator">&gt;</span>vertexCount <span class="operator">*</span> <span class="number">8</span> <span class="operator">*</span> <span class="keyword">sizeof</span>(<span class="type">float</span>);
      bufInfo<span class="operator">.</span>size <span class="operator">=</span> blockMeshByteCount;
      bufInfo<span class="operator">.</span>usage <span class="operator">=</span> VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
      VkResult err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCreateBuffer(dev<span class="operator">,</span> <span class="operator">&amp;</span>bufInfo<span class="operator">,</span> nullptr<span class="operator">,</span> <span class="operator">&amp;</span>m_blockVertexBuf);
      <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
          <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to create vertex buffer: %d&quot;</span><span class="operator">,</span> err);

      VkMemoryRequirements blockVertMemReq;
      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkGetBufferMemoryRequirements(dev<span class="operator">,</span> m_blockVertexBuf<span class="operator">,</span> <span class="operator">&amp;</span>blockVertMemReq);

      <span class="comment">// Vertex buffer for the logo.</span>
      <span class="keyword">const</span> <span class="type">int</span> logoMeshByteCount <span class="operator">=</span> m_logoMesh<span class="operator">.</span>data()<span class="operator">-</span><span class="operator">&gt;</span>vertexCount <span class="operator">*</span> <span class="number">8</span> <span class="operator">*</span> <span class="keyword">sizeof</span>(<span class="type">float</span>);
      bufInfo<span class="operator">.</span>size <span class="operator">=</span> logoMeshByteCount;
      bufInfo<span class="operator">.</span>usage <span class="operator">=</span> VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
      err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCreateBuffer(dev<span class="operator">,</span> <span class="operator">&amp;</span>bufInfo<span class="operator">,</span> nullptr<span class="operator">,</span> <span class="operator">&amp;</span>m_logoVertexBuf);
      <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
          <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to create vertex buffer: %d&quot;</span><span class="operator">,</span> err);

      VkMemoryRequirements logoVertMemReq;
      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkGetBufferMemoryRequirements(dev<span class="operator">,</span> m_logoVertexBuf<span class="operator">,</span> <span class="operator">&amp;</span>logoVertMemReq);

      <span class="comment">// Vertex buffer for the floor.</span>
      bufInfo<span class="operator">.</span>size <span class="operator">=</span> <span class="keyword">sizeof</span>(quadVert);
      err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCreateBuffer(dev<span class="operator">,</span> <span class="operator">&amp;</span>bufInfo<span class="operator">,</span> nullptr<span class="operator">,</span> <span class="operator">&amp;</span>m_floorVertexBuf);
      <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
          <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to create vertex buffer: %d&quot;</span><span class="operator">,</span> err);

      VkMemoryRequirements floorVertMemReq;
      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkGetBufferMemoryRequirements(dev<span class="operator">,</span> m_floorVertexBuf<span class="operator">,</span> <span class="operator">&amp;</span>floorVertMemReq);

      <span class="comment">// Uniform buffer. Instead of using multiple descriptor sets, we take a</span>
      <span class="comment">// different approach: have a single dynamic uniform buffer and specify the</span>
      <span class="comment">// active-frame-specific offset at the time of binding the descriptor set.</span>
      bufInfo<span class="operator">.</span>size <span class="operator">=</span> (m_itemMaterial<span class="operator">.</span>vertUniSize <span class="operator">+</span> m_itemMaterial<span class="operator">.</span>fragUniSize) <span class="operator">*</span> concurrentFrameCount;
      bufInfo<span class="operator">.</span>usage <span class="operator">=</span> VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
      err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCreateBuffer(dev<span class="operator">,</span> <span class="operator">&amp;</span>bufInfo<span class="operator">,</span> nullptr<span class="operator">,</span> <span class="operator">&amp;</span>m_uniBuf);
      <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
          <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to create uniform buffer: %d&quot;</span><span class="operator">,</span> err);

      VkMemoryRequirements uniMemReq;
      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkGetBufferMemoryRequirements(dev<span class="operator">,</span> m_uniBuf<span class="operator">,</span> <span class="operator">&amp;</span>uniMemReq);

      <span class="comment">// Allocate memory for everything at once.</span>
      VkDeviceSize logoVertStartOffset <span class="operator">=</span> aligned(<span class="number">0</span> <span class="operator">+</span> blockVertMemReq<span class="operator">.</span>size<span class="operator">,</span> logoVertMemReq<span class="operator">.</span>alignment);
      VkDeviceSize floorVertStartOffset <span class="operator">=</span> aligned(logoVertStartOffset <span class="operator">+</span> logoVertMemReq<span class="operator">.</span>size<span class="operator">,</span> floorVertMemReq<span class="operator">.</span>alignment);
      m_itemMaterial<span class="operator">.</span>uniMemStartOffset <span class="operator">=</span> aligned(floorVertStartOffset <span class="operator">+</span> floorVertMemReq<span class="operator">.</span>size<span class="operator">,</span> uniMemReq<span class="operator">.</span>alignment);
      VkMemoryAllocateInfo memAllocInfo <span class="operator">=</span> {
          VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO<span class="operator">,</span>
          nullptr<span class="operator">,</span>
          m_itemMaterial<span class="operator">.</span>uniMemStartOffset <span class="operator">+</span> uniMemReq<span class="operator">.</span>size<span class="operator">,</span>
          m_window<span class="operator">-</span><span class="operator">&gt;</span>hostVisibleMemoryIndex()
      };
      err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkAllocateMemory(dev<span class="operator">,</span> <span class="operator">&amp;</span>memAllocInfo<span class="operator">,</span> nullptr<span class="operator">,</span> <span class="operator">&amp;</span>m_bufMem);
      <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
          <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to allocate memory: %d&quot;</span><span class="operator">,</span> err);

      err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkBindBufferMemory(dev<span class="operator">,</span> m_blockVertexBuf<span class="operator">,</span> m_bufMem<span class="operator">,</span> <span class="number">0</span>);
      <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
          <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to bind vertex buffer memory: %d&quot;</span><span class="operator">,</span> err);
      err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkBindBufferMemory(dev<span class="operator">,</span> m_logoVertexBuf<span class="operator">,</span> m_bufMem<span class="operator">,</span> logoVertStartOffset);
      <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
          <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to bind vertex buffer memory: %d&quot;</span><span class="operator">,</span> err);
      err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkBindBufferMemory(dev<span class="operator">,</span> m_floorVertexBuf<span class="operator">,</span> m_bufMem<span class="operator">,</span> floorVertStartOffset);
      <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
          <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to bind vertex buffer memory: %d&quot;</span><span class="operator">,</span> err);
      err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkBindBufferMemory(dev<span class="operator">,</span> m_uniBuf<span class="operator">,</span> m_bufMem<span class="operator">,</span> m_itemMaterial<span class="operator">.</span>uniMemStartOffset);
      <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
          <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to bind uniform buffer memory: %d&quot;</span><span class="operator">,</span> err);

      <span class="comment">// Copy vertex data.</span>
      <span class="type"><a href="../qtcore/qtglobal.html#quint8-typedef">quint8</a></span> <span class="operator">*</span>p;
      err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkMapMemory(dev<span class="operator">,</span> m_bufMem<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> m_itemMaterial<span class="operator">.</span>uniMemStartOffset<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">reinterpret_cast</span><span class="operator">&lt;</span><span class="type">void</span> <span class="operator">*</span><span class="operator">*</span><span class="operator">&gt;</span>(<span class="operator">&amp;</span>p));
      <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
          <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to map memory: %d&quot;</span><span class="operator">,</span> err);
      memcpy(p<span class="operator">,</span> m_blockMesh<span class="operator">.</span>data()<span class="operator">-</span><span class="operator">&gt;</span>geom<span class="operator">.</span>constData()<span class="operator">,</span> blockMeshByteCount);
      memcpy(p <span class="operator">+</span> logoVertStartOffset<span class="operator">,</span> m_logoMesh<span class="operator">.</span>data()<span class="operator">-</span><span class="operator">&gt;</span>geom<span class="operator">.</span>constData()<span class="operator">,</span> logoMeshByteCount);
      memcpy(p <span class="operator">+</span> floorVertStartOffset<span class="operator">,</span> quadVert<span class="operator">,</span> <span class="keyword">sizeof</span>(quadVert));
      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkUnmapMemory(dev<span class="operator">,</span> m_bufMem);

      <span class="comment">// Write descriptors for the uniform buffers in the vertex and fragment shaders.</span>
      VkDescriptorBufferInfo vertUni <span class="operator">=</span> { m_uniBuf<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> m_itemMaterial<span class="operator">.</span>vertUniSize };
      VkDescriptorBufferInfo fragUni <span class="operator">=</span> { m_uniBuf<span class="operator">,</span> m_itemMaterial<span class="operator">.</span>vertUniSize<span class="operator">,</span> m_itemMaterial<span class="operator">.</span>fragUniSize };

      VkWriteDescriptorSet descWrite<span class="operator">[</span><span class="number">2</span><span class="operator">]</span>;
      memset(descWrite<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(descWrite));
      descWrite<span class="operator">[</span><span class="number">0</span><span class="operator">]</span><span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
      descWrite<span class="operator">[</span><span class="number">0</span><span class="operator">]</span><span class="operator">.</span>dstSet <span class="operator">=</span> m_itemMaterial<span class="operator">.</span>descSet;
      descWrite<span class="operator">[</span><span class="number">0</span><span class="operator">]</span><span class="operator">.</span>dstBinding <span class="operator">=</span> <span class="number">0</span>;
      descWrite<span class="operator">[</span><span class="number">0</span><span class="operator">]</span><span class="operator">.</span>descriptorCount <span class="operator">=</span> <span class="number">1</span>;
      descWrite<span class="operator">[</span><span class="number">0</span><span class="operator">]</span><span class="operator">.</span>descriptorType <span class="operator">=</span> VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
      descWrite<span class="operator">[</span><span class="number">0</span><span class="operator">]</span><span class="operator">.</span>pBufferInfo <span class="operator">=</span> <span class="operator">&amp;</span>vertUni;

      descWrite<span class="operator">[</span><span class="number">1</span><span class="operator">]</span><span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
      descWrite<span class="operator">[</span><span class="number">1</span><span class="operator">]</span><span class="operator">.</span>dstSet <span class="operator">=</span> m_itemMaterial<span class="operator">.</span>descSet;
      descWrite<span class="operator">[</span><span class="number">1</span><span class="operator">]</span><span class="operator">.</span>dstBinding <span class="operator">=</span> <span class="number">1</span>;
      descWrite<span class="operator">[</span><span class="number">1</span><span class="operator">]</span><span class="operator">.</span>descriptorCount <span class="operator">=</span> <span class="number">1</span>;
      descWrite<span class="operator">[</span><span class="number">1</span><span class="operator">]</span><span class="operator">.</span>descriptorType <span class="operator">=</span> VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
      descWrite<span class="operator">[</span><span class="number">1</span><span class="operator">]</span><span class="operator">.</span>pBufferInfo <span class="operator">=</span> <span class="operator">&amp;</span>fragUni;

      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkUpdateDescriptorSets(dev<span class="operator">,</span> <span class="number">2</span><span class="operator">,</span> descWrite<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> nullptr);
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>ensureInstanceBuffer()
  {
      <span class="keyword">if</span> (m_instCount <span class="operator">=</span><span class="operator">=</span> m_preparedInstCount <span class="operator">&amp;</span><span class="operator">&amp;</span> m_instBuf)
          <span class="keyword">return</span>;

      Q_ASSERT(m_instCount <span class="operator">&lt;</span><span class="operator">=</span> MAX_INSTANCES);

      VkDevice dev <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>device();

      <span class="comment">// allocate only once, for the maximum instance count</span>
      <span class="keyword">if</span> (<span class="operator">!</span>m_instBuf) {
          VkBufferCreateInfo bufInfo;
          memset(<span class="operator">&amp;</span>bufInfo<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(bufInfo));
          bufInfo<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
          bufInfo<span class="operator">.</span>size <span class="operator">=</span> MAX_INSTANCES <span class="operator">*</span> PER_INSTANCE_DATA_SIZE;
          bufInfo<span class="operator">.</span>usage <span class="operator">=</span> VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;

          <span class="comment">// Keep a copy of the data since we may lose all graphics resources on</span>
          <span class="comment">// unexpose, and reinitializing to new random positions afterwards</span>
          <span class="comment">// would not be nice.</span>
          m_instData<span class="operator">.</span>resize(bufInfo<span class="operator">.</span>size);

          VkResult err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCreateBuffer(dev<span class="operator">,</span> <span class="operator">&amp;</span>bufInfo<span class="operator">,</span> nullptr<span class="operator">,</span> <span class="operator">&amp;</span>m_instBuf);
          <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
              <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to create instance buffer: %d&quot;</span><span class="operator">,</span> err);

          VkMemoryRequirements memReq;
          m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkGetBufferMemoryRequirements(dev<span class="operator">,</span> m_instBuf<span class="operator">,</span> <span class="operator">&amp;</span>memReq);
          <span class="keyword">if</span> (DBG)
              <a href="../qtcore/qtglobal.html#qDebug">qDebug</a>(<span class="string">&quot;Allocating %u bytes for instance data&quot;</span><span class="operator">,</span> uint32_t(memReq<span class="operator">.</span>size));

          VkMemoryAllocateInfo memAllocInfo <span class="operator">=</span> {
              VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO<span class="operator">,</span>
              nullptr<span class="operator">,</span>
              memReq<span class="operator">.</span>size<span class="operator">,</span>
              m_window<span class="operator">-</span><span class="operator">&gt;</span>hostVisibleMemoryIndex()
          };
          err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkAllocateMemory(dev<span class="operator">,</span> <span class="operator">&amp;</span>memAllocInfo<span class="operator">,</span> nullptr<span class="operator">,</span> <span class="operator">&amp;</span>m_instBufMem);
          <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
              <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to allocate memory: %d&quot;</span><span class="operator">,</span> err);

          err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkBindBufferMemory(dev<span class="operator">,</span> m_instBuf<span class="operator">,</span> m_instBufMem<span class="operator">,</span> <span class="number">0</span>);
          <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
              <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to bind instance buffer memory: %d&quot;</span><span class="operator">,</span> err);
      }

      <span class="keyword">if</span> (m_instCount <span class="operator">!</span><span class="operator">=</span> m_preparedInstCount) {
          <span class="keyword">if</span> (DBG)
              <a href="../qtcore/qtglobal.html#qDebug">qDebug</a>(<span class="string">&quot;Preparing instances %d..%d&quot;</span><span class="operator">,</span> m_preparedInstCount<span class="operator">,</span> m_instCount <span class="operator">-</span> <span class="number">1</span>);
          <span class="type">char</span> <span class="operator">*</span>p <span class="operator">=</span> m_instData<span class="operator">.</span>data();
          p <span class="operator">+</span><span class="operator">=</span> m_preparedInstCount <span class="operator">*</span> PER_INSTANCE_DATA_SIZE;
          <span class="keyword">auto</span> gen <span class="operator">=</span> <span class="operator">[</span><span class="operator">]</span>(<span class="type">float</span> a<span class="operator">,</span> <span class="type">float</span> b) { <span class="keyword">return</span> <span class="type">float</span>((qrand() <span class="operator">%</span> <span class="type">int</span>(b <span class="operator">-</span> a <span class="operator">+</span> <span class="number">1</span>)) <span class="operator">+</span> a); };
          <span class="keyword">for</span> (<span class="type">int</span> i <span class="operator">=</span> m_preparedInstCount; i <span class="operator">&lt;</span> m_instCount; <span class="operator">+</span><span class="operator">+</span>i) {
              <span class="comment">// Apply a random translation to each instance of the mesh.</span>
              <span class="type">float</span> t<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> { gen(<span class="operator">-</span><span class="number">5</span><span class="operator">,</span> <span class="number">5</span>)<span class="operator">,</span> gen(<span class="operator">-</span><span class="number">4</span><span class="operator">,</span> <span class="number">6</span>)<span class="operator">,</span> gen(<span class="operator">-</span><span class="number">30</span><span class="operator">,</span> <span class="number">5</span>) };
              memcpy(p<span class="operator">,</span> t<span class="operator">,</span> <span class="number">12</span>);
              <span class="comment">// Apply a random adjustment to the diffuse color for each instance. (default is 0.7)</span>
              <span class="type">float</span> d<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> { gen(<span class="operator">-</span><span class="number">6</span><span class="operator">,</span> <span class="number">3</span>) <span class="operator">/</span> <span class="number">10.0f</span><span class="operator">,</span> gen(<span class="operator">-</span><span class="number">6</span><span class="operator">,</span> <span class="number">3</span>) <span class="operator">/</span> <span class="number">10.0f</span><span class="operator">,</span> gen(<span class="operator">-</span><span class="number">6</span><span class="operator">,</span> <span class="number">3</span>) <span class="operator">/</span> <span class="number">10.0f</span> };
              memcpy(p <span class="operator">+</span> <span class="number">12</span><span class="operator">,</span> d<span class="operator">,</span> <span class="number">12</span>);
              p <span class="operator">+</span><span class="operator">=</span> PER_INSTANCE_DATA_SIZE;
          }
          m_preparedInstCount <span class="operator">=</span> m_instCount;
      }

      <span class="type"><a href="../qtcore/qtglobal.html#quint8-typedef">quint8</a></span> <span class="operator">*</span>p;
      VkResult err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkMapMemory(dev<span class="operator">,</span> m_instBufMem<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> m_instCount <span class="operator">*</span> PER_INSTANCE_DATA_SIZE<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span>
                                             <span class="keyword">reinterpret_cast</span><span class="operator">&lt;</span><span class="type">void</span> <span class="operator">*</span><span class="operator">*</span><span class="operator">&gt;</span>(<span class="operator">&amp;</span>p));
      <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
          <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to map memory: %d&quot;</span><span class="operator">,</span> err);
      memcpy(p<span class="operator">,</span> m_instData<span class="operator">.</span>constData()<span class="operator">,</span> m_instData<span class="operator">.</span>size());
      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkUnmapMemory(dev<span class="operator">,</span> m_instBufMem);
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>getMatrices(QMatrix4x4 <span class="operator">*</span>vp<span class="operator">,</span> QMatrix4x4 <span class="operator">*</span>model<span class="operator">,</span> QMatrix3x3 <span class="operator">*</span>modelNormal<span class="operator">,</span> QVector3D <span class="operator">*</span>eyePos)
  {
      model<span class="operator">-</span><span class="operator">&gt;</span>setToIdentity();
      <span class="keyword">if</span> (m_useLogo)
          model<span class="operator">-</span><span class="operator">&gt;</span>rotate(<span class="number">90</span><span class="operator">,</span> <span class="number">1</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="number">0</span>);
      model<span class="operator">-</span><span class="operator">&gt;</span>rotate(m_rotation<span class="operator">,</span> <span class="number">1</span><span class="operator">,</span> <span class="number">1</span><span class="operator">,</span> <span class="number">0</span>);

      <span class="operator">*</span>modelNormal <span class="operator">=</span> model<span class="operator">-</span><span class="operator">&gt;</span>normalMatrix();

      QMatrix4x4 view <span class="operator">=</span> m_cam<span class="operator">.</span>viewMatrix();
      <span class="operator">*</span>vp <span class="operator">=</span> m_proj <span class="operator">*</span> view;

      <span class="operator">*</span>eyePos <span class="operator">=</span> view<span class="operator">.</span>inverted()<span class="operator">.</span>column(<span class="number">3</span>)<span class="operator">.</span>toVector3D();
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>writeFragUni(<span class="type"><a href="../qtcore/qtglobal.html#quint8-typedef">quint8</a></span> <span class="operator">*</span>p<span class="operator">,</span> <span class="keyword">const</span> QVector3D <span class="operator">&amp;</span>eyePos)
  {
      <span class="type">float</span> ECCameraPosition<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> { eyePos<span class="operator">.</span>x()<span class="operator">,</span> eyePos<span class="operator">.</span>y()<span class="operator">,</span> eyePos<span class="operator">.</span>z() };
      memcpy(p<span class="operator">,</span> ECCameraPosition<span class="operator">,</span> <span class="number">12</span>);
      p <span class="operator">+</span><span class="operator">=</span> <span class="number">16</span>;

      <span class="comment">// Material</span>
      <span class="type">float</span> ka<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> { <span class="number">0.05f</span><span class="operator">,</span> <span class="number">0.05f</span><span class="operator">,</span> <span class="number">0.05f</span> };
      memcpy(p<span class="operator">,</span> ka<span class="operator">,</span> <span class="number">12</span>);
      p <span class="operator">+</span><span class="operator">=</span> <span class="number">16</span>;

      <span class="type">float</span> kd<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> { <span class="number">0.7f</span><span class="operator">,</span> <span class="number">0.7f</span><span class="operator">,</span> <span class="number">0.7f</span> };
      memcpy(p<span class="operator">,</span> kd<span class="operator">,</span> <span class="number">12</span>);
      p <span class="operator">+</span><span class="operator">=</span> <span class="number">16</span>;

      <span class="type">float</span> ks<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> { <span class="number">0.66f</span><span class="operator">,</span> <span class="number">0.66f</span><span class="operator">,</span> <span class="number">0.66f</span> };
      memcpy(p<span class="operator">,</span> ks<span class="operator">,</span> <span class="number">12</span>);
      p <span class="operator">+</span><span class="operator">=</span> <span class="number">16</span>;

      <span class="comment">// Light parameters</span>
      <span class="type">float</span> ECLightPosition<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> { m_lightPos<span class="operator">.</span>x()<span class="operator">,</span> m_lightPos<span class="operator">.</span>y()<span class="operator">,</span> m_lightPos<span class="operator">.</span>z() };
      memcpy(p<span class="operator">,</span> ECLightPosition<span class="operator">,</span> <span class="number">12</span>);
      p <span class="operator">+</span><span class="operator">=</span> <span class="number">16</span>;

      <span class="type">float</span> att<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> { <span class="number">1</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="number">0</span> };
      memcpy(p<span class="operator">,</span> att<span class="operator">,</span> <span class="number">12</span>);
      p <span class="operator">+</span><span class="operator">=</span> <span class="number">16</span>;

      <span class="type">float</span> color<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> { <span class="number">1.0f</span><span class="operator">,</span> <span class="number">1.0f</span><span class="operator">,</span> <span class="number">1.0f</span> };
      memcpy(p<span class="operator">,</span> color<span class="operator">,</span> <span class="number">12</span>);
      p <span class="operator">+</span><span class="operator">=</span> <span class="number">12</span>; <span class="comment">// next we have two floats which have an alignment of 4, hence 12 only</span>

      <span class="type">float</span> intensity <span class="operator">=</span> <span class="number">0.8f</span>;
      memcpy(p<span class="operator">,</span> <span class="operator">&amp;</span>intensity<span class="operator">,</span> <span class="number">4</span>);
      p <span class="operator">+</span><span class="operator">=</span> <span class="number">4</span>;

      <span class="type">float</span> specularExp <span class="operator">=</span> <span class="number">150.0f</span>;
      memcpy(p<span class="operator">,</span> <span class="operator">&amp;</span>specularExp<span class="operator">,</span> <span class="number">4</span>);
      p <span class="operator">+</span><span class="operator">=</span> <span class="number">4</span>;
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>startNextFrame()
  {
      <span class="comment">// For demonstration purposes offload the command buffer generation onto a</span>
      <span class="comment">// worker thread and continue with the frame submission only when it has</span>
      <span class="comment">// finished.</span>
      Q_ASSERT(<span class="operator">!</span>m_framePending);
      m_framePending <span class="operator">=</span> <span class="keyword">true</span>;
      <span class="type"><a href="../qtcore/qfuture.html">QFuture</a></span><span class="operator">&lt;</span><span class="type">void</span><span class="operator">&gt;</span> future <span class="operator">=</span> <span class="type">QtConcurrent</span><span class="operator">::</span>run(<span class="keyword">this</span><span class="operator">,</span> <span class="operator">&amp;</span>Renderer<span class="operator">::</span>buildFrame);
      m_frameWatcher<span class="operator">.</span>setFuture(future);
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>buildFrame()
  {
      <span class="type"><a href="../qtcore/qmutexlocker.html">QMutexLocker</a></span> locker(<span class="operator">&amp;</span>m_guiMutex);

      ensureBuffers();
      ensureInstanceBuffer();
      m_pipelinesFuture<span class="operator">.</span>waitForFinished();

      VkCommandBuffer cb <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>currentCommandBuffer();
      <span class="keyword">const</span> <span class="type"><a href="../qtcore/qsize.html">QSize</a></span> sz <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>swapChainImageSize();

      VkClearColorValue clearColor <span class="operator">=</span> {{ <span class="number">0.67f</span><span class="operator">,</span> <span class="number">0.84f</span><span class="operator">,</span> <span class="number">0.9f</span><span class="operator">,</span> <span class="number">1.0f</span> }};
      VkClearDepthStencilValue clearDS <span class="operator">=</span> { <span class="number">1</span><span class="operator">,</span> <span class="number">0</span> };
      VkClearValue clearValues<span class="operator">[</span><span class="number">3</span><span class="operator">]</span>;
      memset(clearValues<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(clearValues));
      clearValues<span class="operator">[</span><span class="number">0</span><span class="operator">]</span><span class="operator">.</span>color <span class="operator">=</span> clearValues<span class="operator">[</span><span class="number">2</span><span class="operator">]</span><span class="operator">.</span>color <span class="operator">=</span> clearColor;
      clearValues<span class="operator">[</span><span class="number">1</span><span class="operator">]</span><span class="operator">.</span>depthStencil <span class="operator">=</span> clearDS;

      VkRenderPassBeginInfo rpBeginInfo;
      memset(<span class="operator">&amp;</span>rpBeginInfo<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="keyword">sizeof</span>(rpBeginInfo));
      rpBeginInfo<span class="operator">.</span>sType <span class="operator">=</span> VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
      rpBeginInfo<span class="operator">.</span>renderPass <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>defaultRenderPass();
      rpBeginInfo<span class="operator">.</span>framebuffer <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>currentFramebuffer();
      rpBeginInfo<span class="operator">.</span>renderArea<span class="operator">.</span>extent<span class="operator">.</span>width <span class="operator">=</span> sz<span class="operator">.</span>width();
      rpBeginInfo<span class="operator">.</span>renderArea<span class="operator">.</span>extent<span class="operator">.</span>height <span class="operator">=</span> sz<span class="operator">.</span>height();
      rpBeginInfo<span class="operator">.</span>clearValueCount <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>sampleCountFlagBits() <span class="operator">&gt;</span> VK_SAMPLE_COUNT_1_BIT <span class="operator">?</span> <span class="number">3</span> : <span class="number">2</span>;
      rpBeginInfo<span class="operator">.</span>pClearValues <span class="operator">=</span> clearValues;
      VkCommandBuffer cmdBuf <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>currentCommandBuffer();
      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCmdBeginRenderPass(cmdBuf<span class="operator">,</span> <span class="operator">&amp;</span>rpBeginInfo<span class="operator">,</span> VK_SUBPASS_CONTENTS_INLINE);

      VkViewport viewport <span class="operator">=</span> {
          <span class="number">0</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span>
          <span class="type">float</span>(sz<span class="operator">.</span>width())<span class="operator">,</span> <span class="type">float</span>(sz<span class="operator">.</span>height())<span class="operator">,</span>
          <span class="number">0</span><span class="operator">,</span> <span class="number">1</span>
      };
      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCmdSetViewport(cb<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="number">1</span><span class="operator">,</span> <span class="operator">&amp;</span>viewport);

      VkRect2D scissor <span class="operator">=</span> {
          { <span class="number">0</span><span class="operator">,</span> <span class="number">0</span> }<span class="operator">,</span>
          { uint32_t(sz<span class="operator">.</span>width())<span class="operator">,</span> uint32_t(sz<span class="operator">.</span>height()) }
      };
      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCmdSetScissor(cb<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="number">1</span><span class="operator">,</span> <span class="operator">&amp;</span>scissor);

      buildDrawCallsForFloor();
      buildDrawCallsForItems();

      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCmdEndRenderPass(cmdBuf);
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>buildDrawCallsForItems()
  {
      VkDevice dev <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>device();
      VkCommandBuffer cb <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>currentCommandBuffer();

      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCmdBindPipeline(cb<span class="operator">,</span> VK_PIPELINE_BIND_POINT_GRAPHICS<span class="operator">,</span> m_itemMaterial<span class="operator">.</span>pipeline);

      VkDeviceSize vbOffset <span class="operator">=</span> <span class="number">0</span>;
      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCmdBindVertexBuffers(cb<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="number">1</span><span class="operator">,</span> m_useLogo <span class="operator">?</span> <span class="operator">&amp;</span>m_logoVertexBuf : <span class="operator">&amp;</span>m_blockVertexBuf<span class="operator">,</span> <span class="operator">&amp;</span>vbOffset);
      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCmdBindVertexBuffers(cb<span class="operator">,</span> <span class="number">1</span><span class="operator">,</span> <span class="number">1</span><span class="operator">,</span> <span class="operator">&amp;</span>m_instBuf<span class="operator">,</span> <span class="operator">&amp;</span>vbOffset);

      <span class="comment">// Now provide offsets so that the two dynamic buffers point to the</span>
      <span class="comment">// beginning of the vertex and fragment uniform data for the current frame.</span>
      uint32_t frameUniOffset <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>currentFrame() <span class="operator">*</span> (m_itemMaterial<span class="operator">.</span>vertUniSize <span class="operator">+</span> m_itemMaterial<span class="operator">.</span>fragUniSize);
      uint32_t frameUniOffsets<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> { frameUniOffset<span class="operator">,</span> frameUniOffset };
      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCmdBindDescriptorSets(cb<span class="operator">,</span> VK_PIPELINE_BIND_POINT_GRAPHICS<span class="operator">,</span> m_itemMaterial<span class="operator">.</span>pipelineLayout<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="number">1</span><span class="operator">,</span>
                                          <span class="operator">&amp;</span>m_itemMaterial<span class="operator">.</span>descSet<span class="operator">,</span> <span class="number">2</span><span class="operator">,</span> frameUniOffsets);

      <span class="keyword">if</span> (m_animating)
          m_rotation <span class="operator">+</span><span class="operator">=</span> <span class="number">0.5</span>;

      <span class="keyword">if</span> (m_animating <span class="operator">|</span><span class="operator">|</span> m_vpDirty) {
          <span class="keyword">if</span> (m_vpDirty)
              <span class="operator">-</span><span class="operator">-</span>m_vpDirty;
          QMatrix4x4 vp<span class="operator">,</span> model;
          QMatrix3x3 modelNormal;
          QVector3D eyePos;
          getMatrices(<span class="operator">&amp;</span>vp<span class="operator">,</span> <span class="operator">&amp;</span>model<span class="operator">,</span> <span class="operator">&amp;</span>modelNormal<span class="operator">,</span> <span class="operator">&amp;</span>eyePos);

          <span class="comment">// Map the uniform data for the current frame, ignore the geometry data at</span>
          <span class="comment">// the beginning and the uniforms for other frames.</span>
          <span class="type"><a href="../qtcore/qtglobal.html#quint8-typedef">quint8</a></span> <span class="operator">*</span>p;
          VkResult err <span class="operator">=</span> m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkMapMemory(dev<span class="operator">,</span> m_bufMem<span class="operator">,</span>
                                                 m_itemMaterial<span class="operator">.</span>uniMemStartOffset <span class="operator">+</span> frameUniOffset<span class="operator">,</span>
                                                 m_itemMaterial<span class="operator">.</span>vertUniSize <span class="operator">+</span> m_itemMaterial<span class="operator">.</span>fragUniSize<span class="operator">,</span>
                                                 <span class="number">0</span><span class="operator">,</span> <span class="keyword">reinterpret_cast</span><span class="operator">&lt;</span><span class="type">void</span> <span class="operator">*</span><span class="operator">*</span><span class="operator">&gt;</span>(<span class="operator">&amp;</span>p));
          <span class="keyword">if</span> (err <span class="operator">!</span><span class="operator">=</span> VK_SUCCESS)
              <a href="../qtcore/qtglobal.html#qFatal">qFatal</a>(<span class="string">&quot;Failed to map memory: %d&quot;</span><span class="operator">,</span> err);

          <span class="comment">// Vertex shader uniforms</span>
          memcpy(p<span class="operator">,</span> vp<span class="operator">.</span>constData()<span class="operator">,</span> <span class="number">64</span>);
          memcpy(p <span class="operator">+</span> <span class="number">64</span><span class="operator">,</span> model<span class="operator">.</span>constData()<span class="operator">,</span> <span class="number">64</span>);
          <span class="keyword">const</span> <span class="type">float</span> <span class="operator">*</span>mnp <span class="operator">=</span> modelNormal<span class="operator">.</span>constData();
          memcpy(p <span class="operator">+</span> <span class="number">128</span><span class="operator">,</span> mnp<span class="operator">,</span> <span class="number">12</span>);
          memcpy(p <span class="operator">+</span> <span class="number">128</span> <span class="operator">+</span> <span class="number">16</span><span class="operator">,</span> mnp <span class="operator">+</span> <span class="number">3</span><span class="operator">,</span> <span class="number">12</span>);
          memcpy(p <span class="operator">+</span> <span class="number">128</span> <span class="operator">+</span> <span class="number">32</span><span class="operator">,</span> mnp <span class="operator">+</span> <span class="number">6</span><span class="operator">,</span> <span class="number">12</span>);

          <span class="comment">// Fragment shader uniforms</span>
          p <span class="operator">+</span><span class="operator">=</span> m_itemMaterial<span class="operator">.</span>vertUniSize;
          writeFragUni(p<span class="operator">,</span> eyePos);

          m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkUnmapMemory(dev<span class="operator">,</span> m_bufMem);
      }

      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCmdDraw(cb<span class="operator">,</span> (m_useLogo <span class="operator">?</span> m_logoMesh<span class="operator">.</span>data() : m_blockMesh<span class="operator">.</span>data())<span class="operator">-</span><span class="operator">&gt;</span>vertexCount<span class="operator">,</span> m_instCount<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="number">0</span>);
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>buildDrawCallsForFloor()
  {
      VkCommandBuffer cb <span class="operator">=</span> m_window<span class="operator">-</span><span class="operator">&gt;</span>currentCommandBuffer();

      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCmdBindPipeline(cb<span class="operator">,</span> VK_PIPELINE_BIND_POINT_GRAPHICS<span class="operator">,</span> m_floorMaterial<span class="operator">.</span>pipeline);

      VkDeviceSize vbOffset <span class="operator">=</span> <span class="number">0</span>;
      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCmdBindVertexBuffers(cb<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="number">1</span><span class="operator">,</span> <span class="operator">&amp;</span>m_floorVertexBuf<span class="operator">,</span> <span class="operator">&amp;</span>vbOffset);

      QMatrix4x4 mvp <span class="operator">=</span> m_proj <span class="operator">*</span> m_cam<span class="operator">.</span>viewMatrix() <span class="operator">*</span> m_floorModel;
      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCmdPushConstants(cb<span class="operator">,</span> m_floorMaterial<span class="operator">.</span>pipelineLayout<span class="operator">,</span> VK_SHADER_STAGE_VERTEX_BIT<span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="number">64</span><span class="operator">,</span> mvp<span class="operator">.</span>constData());
      <span class="type">float</span> color<span class="operator">[</span><span class="operator">]</span> <span class="operator">=</span> { <span class="number">0.67f</span><span class="operator">,</span> <span class="number">1.0f</span><span class="operator">,</span> <span class="number">0.2f</span> };
      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCmdPushConstants(cb<span class="operator">,</span> m_floorMaterial<span class="operator">.</span>pipelineLayout<span class="operator">,</span> VK_SHADER_STAGE_FRAGMENT_BIT<span class="operator">,</span> <span class="number">64</span><span class="operator">,</span> <span class="number">12</span><span class="operator">,</span> color);

      m_devFuncs<span class="operator">-</span><span class="operator">&gt;</span>vkCmdDraw(cb<span class="operator">,</span> <span class="number">4</span><span class="operator">,</span> <span class="number">1</span><span class="operator">,</span> <span class="number">0</span><span class="operator">,</span> <span class="number">0</span>);
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>addNew()
  {
      <span class="type"><a href="../qtcore/qmutexlocker.html">QMutexLocker</a></span> locker(<span class="operator">&amp;</span>m_guiMutex);
      m_instCount <span class="operator">=</span> <a href="../qtcore/qtglobal.html#qMin">qMin</a>(m_instCount <span class="operator">+</span> <span class="number">16</span><span class="operator">,</span> MAX_INSTANCES);
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>yaw(<span class="type">float</span> degrees)
  {
      <span class="type"><a href="../qtcore/qmutexlocker.html">QMutexLocker</a></span> locker(<span class="operator">&amp;</span>m_guiMutex);
      m_cam<span class="operator">.</span>yaw(degrees);
      markViewProjDirty();
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>pitch(<span class="type">float</span> degrees)
  {
      <span class="type"><a href="../qtcore/qmutexlocker.html">QMutexLocker</a></span> locker(<span class="operator">&amp;</span>m_guiMutex);
      m_cam<span class="operator">.</span>pitch(degrees);
      markViewProjDirty();
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>walk(<span class="type">float</span> amount)
  {
      <span class="type"><a href="../qtcore/qmutexlocker.html">QMutexLocker</a></span> locker(<span class="operator">&amp;</span>m_guiMutex);
      m_cam<span class="operator">.</span>walk(amount);
      markViewProjDirty();
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>strafe(<span class="type">float</span> amount)
  {
      <span class="type"><a href="../qtcore/qmutexlocker.html">QMutexLocker</a></span> locker(<span class="operator">&amp;</span>m_guiMutex);
      m_cam<span class="operator">.</span>strafe(amount);
      markViewProjDirty();
  }

  <span class="type">void</span> Renderer<span class="operator">::</span>setUseLogo(bool b)
  {
      <span class="type"><a href="../qtcore/qmutexlocker.html">QMutexLocker</a></span> locker(<span class="operator">&amp;</span>m_guiMutex);
      m_useLogo <span class="operator">=</span> b;
      <span class="keyword">if</span> (<span class="operator">!</span>m_animating)
          m_window<span class="operator">-</span><span class="operator">&gt;</span>requestUpdate();
  }

</pre>
</div>
<!-- @@@hellovulkancubes/renderer.cpp -->
        </div>
       </div>
   </div>
   </div>
</div>
<div class="footer">
   <p>
   <acronym title="Copyright">&copy;</acronym> 2019 The Qt Company Ltd.
   Documentation contributions included herein are the copyrights of
   their respective owners.<br/>    The documentation provided herein is licensed under the terms of the    <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation    License version 1.3</a> as published by the Free Software Foundation.<br/>    Qt and respective logos are trademarks of The Qt Company Ltd.     in Finland and/or other countries worldwide. All other trademarks are property
   of their respective owners. </p>
</div>
</body>
</html>