QtBase  v6.3.1
trianglerenderer.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2017 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the examples of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** BSD License Usage
18 ** Alternatively, you may use this file under the terms of the BSD license
19 ** as follows:
20 **
21 ** "Redistribution and use in source and binary forms, with or without
22 ** modification, are permitted provided that the following conditions are
23 ** met:
24 ** * Redistributions of source code must retain the above copyright
25 ** notice, this list of conditions and the following disclaimer.
26 ** * Redistributions in binary form must reproduce the above copyright
27 ** notice, this list of conditions and the following disclaimer in
28 ** the documentation and/or other materials provided with the
29 ** distribution.
30 ** * Neither the name of The Qt Company Ltd nor the names of its
31 ** contributors may be used to endorse or promote products derived
32 ** from this software without specific prior written permission.
33 **
34 **
35 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 **
47 ** $QT_END_LICENSE$
48 **
49 ****************************************************************************/
50 
51 #include "trianglerenderer.h"
52 #include <QVulkanFunctions>
53 #include <QFile>
54 
55 // Note that the vertex data and the projection matrix assume OpenGL. With
56 // Vulkan Y is negated in clip space and the near/far plane is at 0/1 instead
57 // of -1/1. These will be corrected for by an extra transformation when
58 // calculating the modelview-projection matrix.
59 static float vertexData[] = { // Y up, front = CCW
60  0.0f, 0.5f, 1.0f, 0.0f, 0.0f,
61  -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
62  0.5f, -0.5f, 0.0f, 0.0f, 1.0f
63 };
64 
65 static const int UNIFORM_DATA_SIZE = 16 * sizeof(float);
66 
67 static inline VkDeviceSize aligned(VkDeviceSize v, VkDeviceSize byteAlign)
68 {
69  return (v + byteAlign - 1) & ~(byteAlign - 1);
70 }
71 
73  : m_window(w)
74 {
75  if (msaa) {
76  const QList<int> counts = w->supportedSampleCounts();
77  qDebug() << "Supported sample counts:" << counts;
78  for (int s = 16; s >= 4; s /= 2) {
79  if (counts.contains(s)) {
80  qDebug("Requesting sample count %d", s);
81  m_window->setSampleCount(s);
82  break;
83  }
84  }
85  }
86 }
87 
89 {
90  QFile file(name);
92  qWarning("Failed to read shader %s", qPrintable(name));
93  return VK_NULL_HANDLE;
94  }
95  QByteArray blob = file.readAll();
96  file.close();
97 
98  VkShaderModuleCreateInfo shaderInfo;
99  memset(&shaderInfo, 0, sizeof(shaderInfo));
100  shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
101  shaderInfo.codeSize = blob.size();
102  shaderInfo.pCode = reinterpret_cast<const uint32_t *>(blob.constData());
103  VkShaderModule shaderModule;
104  VkResult err = m_devFuncs->vkCreateShaderModule(m_window->device(), &shaderInfo, nullptr, &shaderModule);
105  if (err != VK_SUCCESS) {
106  qWarning("Failed to create shader module: %d", err);
107  return VK_NULL_HANDLE;
108  }
109 
110  return shaderModule;
111 }
112 
114 {
115  qDebug("initResources");
116 
117  VkDevice dev = m_window->device();
118  m_devFuncs = m_window->vulkanInstance()->deviceFunctions(dev);
119 
120  // Prepare the vertex and uniform data. The vertex data will never
121  // change so one buffer is sufficient regardless of the value of
122  // QVulkanWindow::CONCURRENT_FRAME_COUNT. Uniform data is changing per
123  // frame however so active frames have to have a dedicated copy.
124 
125  // Use just one memory allocation and one buffer. We will then specify the
126  // appropriate offsets for uniform buffers in the VkDescriptorBufferInfo.
127  // Have to watch out for
128  // VkPhysicalDeviceLimits::minUniformBufferOffsetAlignment, though.
129 
130  // The uniform buffer is not strictly required in this example, we could
131  // have used push constants as well since our single matrix (64 bytes) fits
132  // into the spec mandated minimum limit of 128 bytes. However, once that
133  // limit is not sufficient, the per-frame buffers, as shown below, will
134  // become necessary.
135 
136  const int concurrentFrameCount = m_window->concurrentFrameCount();
137  const VkPhysicalDeviceLimits *pdevLimits = &m_window->physicalDeviceProperties()->limits;
138  const VkDeviceSize uniAlign = pdevLimits->minUniformBufferOffsetAlignment;
139  qDebug("uniform buffer offset alignment is %u", (uint) uniAlign);
140  VkBufferCreateInfo bufInfo;
141  memset(&bufInfo, 0, sizeof(bufInfo));
142  bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
143  // Our internal layout is vertex, uniform, uniform, ... with each uniform buffer start offset aligned to uniAlign.
144  const VkDeviceSize vertexAllocSize = aligned(sizeof(vertexData), uniAlign);
145  const VkDeviceSize uniformAllocSize = aligned(UNIFORM_DATA_SIZE, uniAlign);
146  bufInfo.size = vertexAllocSize + concurrentFrameCount * uniformAllocSize;
147  bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
148 
149  VkResult err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_buf);
150  if (err != VK_SUCCESS)
151  qFatal("Failed to create buffer: %d", err);
152 
153  VkMemoryRequirements memReq;
154  m_devFuncs->vkGetBufferMemoryRequirements(dev, m_buf, &memReq);
155 
156  VkMemoryAllocateInfo memAllocInfo = {
157  VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
158  nullptr,
159  memReq.size,
160  m_window->hostVisibleMemoryIndex()
161  };
162 
163  err = m_devFuncs->vkAllocateMemory(dev, &memAllocInfo, nullptr, &m_bufMem);
164  if (err != VK_SUCCESS)
165  qFatal("Failed to allocate memory: %d", err);
166 
167  err = m_devFuncs->vkBindBufferMemory(dev, m_buf, m_bufMem, 0);
168  if (err != VK_SUCCESS)
169  qFatal("Failed to bind buffer memory: %d", err);
170 
171  quint8 *p;
172  err = m_devFuncs->vkMapMemory(dev, m_bufMem, 0, memReq.size, 0, reinterpret_cast<void **>(&p));
173  if (err != VK_SUCCESS)
174  qFatal("Failed to map memory: %d", err);
175  memcpy(p, vertexData, sizeof(vertexData));
177  memset(m_uniformBufInfo, 0, sizeof(m_uniformBufInfo));
178  for (int i = 0; i < concurrentFrameCount; ++i) {
179  const VkDeviceSize offset = vertexAllocSize + i * uniformAllocSize;
180  memcpy(p + offset, ident.constData(), 16 * sizeof(float));
181  m_uniformBufInfo[i].buffer = m_buf;
182  m_uniformBufInfo[i].offset = offset;
183  m_uniformBufInfo[i].range = uniformAllocSize;
184  }
185  m_devFuncs->vkUnmapMemory(dev, m_bufMem);
186 
187  VkVertexInputBindingDescription vertexBindingDesc = {
188  0, // binding
189  5 * sizeof(float),
190  VK_VERTEX_INPUT_RATE_VERTEX
191  };
192  VkVertexInputAttributeDescription vertexAttrDesc[] = {
193  { // position
194  0, // location
195  0, // binding
196  VK_FORMAT_R32G32_SFLOAT,
197  0
198  },
199  { // color
200  1,
201  0,
202  VK_FORMAT_R32G32B32_SFLOAT,
203  2 * sizeof(float)
204  }
205  };
206 
207  VkPipelineVertexInputStateCreateInfo vertexInputInfo;
208  vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
209  vertexInputInfo.pNext = nullptr;
210  vertexInputInfo.flags = 0;
211  vertexInputInfo.vertexBindingDescriptionCount = 1;
212  vertexInputInfo.pVertexBindingDescriptions = &vertexBindingDesc;
213  vertexInputInfo.vertexAttributeDescriptionCount = 2;
214  vertexInputInfo.pVertexAttributeDescriptions = vertexAttrDesc;
215 
216  // Set up descriptor set and its layout.
217  VkDescriptorPoolSize descPoolSizes = { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uint32_t(concurrentFrameCount) };
218  VkDescriptorPoolCreateInfo descPoolInfo;
219  memset(&descPoolInfo, 0, sizeof(descPoolInfo));
220  descPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
221  descPoolInfo.maxSets = concurrentFrameCount;
222  descPoolInfo.poolSizeCount = 1;
223  descPoolInfo.pPoolSizes = &descPoolSizes;
224  err = m_devFuncs->vkCreateDescriptorPool(dev, &descPoolInfo, nullptr, &m_descPool);
225  if (err != VK_SUCCESS)
226  qFatal("Failed to create descriptor pool: %d", err);
227 
228  VkDescriptorSetLayoutBinding layoutBinding = {
229  0, // binding
230  VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
231  1,
232  VK_SHADER_STAGE_VERTEX_BIT,
233  nullptr
234  };
235  VkDescriptorSetLayoutCreateInfo descLayoutInfo = {
236  VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
237  nullptr,
238  0,
239  1,
240  &layoutBinding
241  };
242  err = m_devFuncs->vkCreateDescriptorSetLayout(dev, &descLayoutInfo, nullptr, &m_descSetLayout);
243  if (err != VK_SUCCESS)
244  qFatal("Failed to create descriptor set layout: %d", err);
245 
246  for (int i = 0; i < concurrentFrameCount; ++i) {
247  VkDescriptorSetAllocateInfo descSetAllocInfo = {
248  VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
249  nullptr,
250  m_descPool,
251  1,
253  };
254  err = m_devFuncs->vkAllocateDescriptorSets(dev, &descSetAllocInfo, &m_descSet[i]);
255  if (err != VK_SUCCESS)
256  qFatal("Failed to allocate descriptor set: %d", err);
257 
258  VkWriteDescriptorSet descWrite;
259  memset(&descWrite, 0, sizeof(descWrite));
260  descWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
261  descWrite.dstSet = m_descSet[i];
262  descWrite.descriptorCount = 1;
263  descWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
264  descWrite.pBufferInfo = &m_uniformBufInfo[i];
265  m_devFuncs->vkUpdateDescriptorSets(dev, 1, &descWrite, 0, nullptr);
266  }
267 
268  // Pipeline cache
269  VkPipelineCacheCreateInfo pipelineCacheInfo;
270  memset(&pipelineCacheInfo, 0, sizeof(pipelineCacheInfo));
271  pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
272  err = m_devFuncs->vkCreatePipelineCache(dev, &pipelineCacheInfo, nullptr, &m_pipelineCache);
273  if (err != VK_SUCCESS)
274  qFatal("Failed to create pipeline cache: %d", err);
275 
276  // Pipeline layout
277  VkPipelineLayoutCreateInfo pipelineLayoutInfo;
278  memset(&pipelineLayoutInfo, 0, sizeof(pipelineLayoutInfo));
279  pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
280  pipelineLayoutInfo.setLayoutCount = 1;
281  pipelineLayoutInfo.pSetLayouts = &m_descSetLayout;
282  err = m_devFuncs->vkCreatePipelineLayout(dev, &pipelineLayoutInfo, nullptr, &m_pipelineLayout);
283  if (err != VK_SUCCESS)
284  qFatal("Failed to create pipeline layout: %d", err);
285 
286  // Shaders
287  VkShaderModule vertShaderModule = createShader(QStringLiteral(":/color_vert.spv"));
288  VkShaderModule fragShaderModule = createShader(QStringLiteral(":/color_frag.spv"));
289 
290  // Graphics pipeline
291  VkGraphicsPipelineCreateInfo pipelineInfo;
292  memset(&pipelineInfo, 0, sizeof(pipelineInfo));
293  pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
294 
295  VkPipelineShaderStageCreateInfo shaderStages[2] = {
296  {
297  VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
298  nullptr,
299  0,
300  VK_SHADER_STAGE_VERTEX_BIT,
301  vertShaderModule,
302  "main",
303  nullptr
304  },
305  {
306  VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
307  nullptr,
308  0,
309  VK_SHADER_STAGE_FRAGMENT_BIT,
310  fragShaderModule,
311  "main",
312  nullptr
313  }
314  };
315  pipelineInfo.stageCount = 2;
316  pipelineInfo.pStages = shaderStages;
317 
318  pipelineInfo.pVertexInputState = &vertexInputInfo;
319 
320  VkPipelineInputAssemblyStateCreateInfo ia;
321  memset(&ia, 0, sizeof(ia));
322  ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
323  ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
324  pipelineInfo.pInputAssemblyState = &ia;
325 
326  // The viewport and scissor will be set dynamically via vkCmdSetViewport/Scissor.
327  // This way the pipeline does not need to be touched when resizing the window.
328  VkPipelineViewportStateCreateInfo vp;
329  memset(&vp, 0, sizeof(vp));
330  vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
331  vp.viewportCount = 1;
332  vp.scissorCount = 1;
333  pipelineInfo.pViewportState = &vp;
334 
335  VkPipelineRasterizationStateCreateInfo rs;
336  memset(&rs, 0, sizeof(rs));
337  rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
338  rs.polygonMode = VK_POLYGON_MODE_FILL;
339  rs.cullMode = VK_CULL_MODE_NONE; // we want the back face as well
340  rs.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
341  rs.lineWidth = 1.0f;
342  pipelineInfo.pRasterizationState = &rs;
343 
344  VkPipelineMultisampleStateCreateInfo ms;
345  memset(&ms, 0, sizeof(ms));
346  ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
347  // Enable multisampling.
348  ms.rasterizationSamples = m_window->sampleCountFlagBits();
349  pipelineInfo.pMultisampleState = &ms;
350 
351  VkPipelineDepthStencilStateCreateInfo ds;
352  memset(&ds, 0, sizeof(ds));
353  ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
354  ds.depthTestEnable = VK_TRUE;
355  ds.depthWriteEnable = VK_TRUE;
356  ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
357  pipelineInfo.pDepthStencilState = &ds;
358 
359  VkPipelineColorBlendStateCreateInfo cb;
360  memset(&cb, 0, sizeof(cb));
361  cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
362  // no blend, write out all of rgba
363  VkPipelineColorBlendAttachmentState att;
364  memset(&att, 0, sizeof(att));
365  att.colorWriteMask = 0xF;
366  cb.attachmentCount = 1;
367  cb.pAttachments = &att;
368  pipelineInfo.pColorBlendState = &cb;
369 
370  VkDynamicState dynEnable[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
371  VkPipelineDynamicStateCreateInfo dyn;
372  memset(&dyn, 0, sizeof(dyn));
373  dyn.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
374  dyn.dynamicStateCount = sizeof(dynEnable) / sizeof(VkDynamicState);
375  dyn.pDynamicStates = dynEnable;
376  pipelineInfo.pDynamicState = &dyn;
377 
378  pipelineInfo.layout = m_pipelineLayout;
379  pipelineInfo.renderPass = m_window->defaultRenderPass();
380 
381  err = m_devFuncs->vkCreateGraphicsPipelines(dev, m_pipelineCache, 1, &pipelineInfo, nullptr, &m_pipeline);
382  if (err != VK_SUCCESS)
383  qFatal("Failed to create graphics pipeline: %d", err);
384 
385  if (vertShaderModule)
386  m_devFuncs->vkDestroyShaderModule(dev, vertShaderModule, nullptr);
387  if (fragShaderModule)
388  m_devFuncs->vkDestroyShaderModule(dev, fragShaderModule, nullptr);
389 }
390 
392 {
393  qDebug("initSwapChainResources");
394 
395  // Projection matrix
396  m_proj = m_window->clipCorrectionMatrix(); // adjust for Vulkan-OpenGL clip space differences
397  const QSize sz = m_window->swapChainImageSize();
398  m_proj.perspective(45.0f, sz.width() / (float) sz.height(), 0.01f, 100.0f);
399  m_proj.translate(0, 0, -4);
400 }
401 
403 {
404  qDebug("releaseSwapChainResources");
405 }
406 
408 {
409  qDebug("releaseResources");
410 
411  VkDevice dev = m_window->device();
412 
413  if (m_pipeline) {
414  m_devFuncs->vkDestroyPipeline(dev, m_pipeline, nullptr);
415  m_pipeline = VK_NULL_HANDLE;
416  }
417 
418  if (m_pipelineLayout) {
419  m_devFuncs->vkDestroyPipelineLayout(dev, m_pipelineLayout, nullptr);
420  m_pipelineLayout = VK_NULL_HANDLE;
421  }
422 
423  if (m_pipelineCache) {
424  m_devFuncs->vkDestroyPipelineCache(dev, m_pipelineCache, nullptr);
425  m_pipelineCache = VK_NULL_HANDLE;
426  }
427 
428  if (m_descSetLayout) {
429  m_devFuncs->vkDestroyDescriptorSetLayout(dev, m_descSetLayout, nullptr);
430  m_descSetLayout = VK_NULL_HANDLE;
431  }
432 
433  if (m_descPool) {
434  m_devFuncs->vkDestroyDescriptorPool(dev, m_descPool, nullptr);
435  m_descPool = VK_NULL_HANDLE;
436  }
437 
438  if (m_buf) {
439  m_devFuncs->vkDestroyBuffer(dev, m_buf, nullptr);
440  m_buf = VK_NULL_HANDLE;
441  }
442 
443  if (m_bufMem) {
444  m_devFuncs->vkFreeMemory(dev, m_bufMem, nullptr);
445  m_bufMem = VK_NULL_HANDLE;
446  }
447 }
448 
450 {
451  VkDevice dev = m_window->device();
452  VkCommandBuffer cb = m_window->currentCommandBuffer();
453  const QSize sz = m_window->swapChainImageSize();
454 
455  VkClearColorValue clearColor = {{ 0, 0, 0, 1 }};
456  VkClearDepthStencilValue clearDS = { 1, 0 };
457  VkClearValue clearValues[3];
458  memset(clearValues, 0, sizeof(clearValues));
459  clearValues[0].color = clearValues[2].color = clearColor;
460  clearValues[1].depthStencil = clearDS;
461 
462  VkRenderPassBeginInfo rpBeginInfo;
463  memset(&rpBeginInfo, 0, sizeof(rpBeginInfo));
464  rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
465  rpBeginInfo.renderPass = m_window->defaultRenderPass();
466  rpBeginInfo.framebuffer = m_window->currentFramebuffer();
467  rpBeginInfo.renderArea.extent.width = sz.width();
468  rpBeginInfo.renderArea.extent.height = sz.height();
469  rpBeginInfo.clearValueCount = m_window->sampleCountFlagBits() > VK_SAMPLE_COUNT_1_BIT ? 3 : 2;
470  rpBeginInfo.pClearValues = clearValues;
471  VkCommandBuffer cmdBuf = m_window->currentCommandBuffer();
472  m_devFuncs->vkCmdBeginRenderPass(cmdBuf, &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
473 
474  quint8 *p;
475  VkResult err = m_devFuncs->vkMapMemory(dev, m_bufMem, m_uniformBufInfo[m_window->currentFrame()].offset,
476  UNIFORM_DATA_SIZE, 0, reinterpret_cast<void **>(&p));
477  if (err != VK_SUCCESS)
478  qFatal("Failed to map memory: %d", err);
479  QMatrix4x4 m = m_proj;
480  m.rotate(m_rotation, 0, 1, 0);
481  memcpy(p, m.constData(), 16 * sizeof(float));
482  m_devFuncs->vkUnmapMemory(dev, m_bufMem);
483 
484  // Not exactly a real animation system, just advance on every frame for now.
485  m_rotation += 1.0f;
486 
487  m_devFuncs->vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline);
488  m_devFuncs->vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1,
489  &m_descSet[m_window->currentFrame()], 0, nullptr);
490  VkDeviceSize vbOffset = 0;
491  m_devFuncs->vkCmdBindVertexBuffers(cb, 0, 1, &m_buf, &vbOffset);
492 
493  VkViewport viewport;
494  viewport.x = viewport.y = 0;
495  viewport.width = sz.width();
496  viewport.height = sz.height();
497  viewport.minDepth = 0;
498  viewport.maxDepth = 1;
499  m_devFuncs->vkCmdSetViewport(cb, 0, 1, &viewport);
500 
501  VkRect2D scissor;
502  scissor.offset.x = scissor.offset.y = 0;
503  scissor.extent.width = viewport.width;
504  scissor.extent.height = viewport.height;
505  m_devFuncs->vkCmdSetScissor(cb, 0, 1, &scissor);
506 
507  m_devFuncs->vkCmdDraw(cb, 3, 1, 0, 0);
508 
509  m_devFuncs->vkCmdEndRenderPass(cmdBuf);
510 
511  m_window->frameReady();
512  m_window->requestUpdate(); // render continuously, throttled by the presentation rate
513 }
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:85
qsizetype size() const noexcept
Definition: qbytearray.h:470
const char * constData() const noexcept
Definition: qbytearray.h:144
void close() override
The QFile class provides an interface for reading from and writing to files.
Definition: qfile.h:94
bool open(OpenMode flags) override
Definition: qfile.cpp:897
QByteArray readAll()
Definition: qiodevice.cpp:1268
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition: qmatrix4x4.h:61
void rotate(float angle, const QVector3D &vector)
void perspective(float verticalAngle, float aspectRatio, float nearPlane, float farPlane)
void translate(const QVector3D &vector)
Definition: qmatrix4x4.cpp:965
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:55
constexpr int height() const noexcept
Definition: qsize.h:160
constexpr int width() const noexcept
Definition: qsize.h:157
The QString class provides a Unicode character string.
Definition: qstring.h:388
The QVulkanWindow class is a convenience subclass of QWindow to perform Vulkan rendering.
QVulkanDeviceFunctions * m_devFuncs
VkPipelineLayout m_pipelineLayout
VkDeviceMemory m_bufMem
VkDescriptorSet m_descSet[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT]
VkDescriptorPool m_descPool
VkPipeline m_pipeline
void initSwapChainResources() override
void releaseSwapChainResources() override
void releaseResources() override
VkDescriptorBufferInfo m_uniformBufInfo[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT]
void initResources() override
void startNextFrame() override
TriangleRenderer(QVulkanWindow *w, bool msaa=false)
VkDescriptorSetLayout m_descSetLayout
VkPipelineCache m_pipelineCache
VkShaderModule createShader(const QString &name)
QVulkanWindow * m_window
Token ident
Definition: keywords.cpp:457
std::chrono::milliseconds ms
unsigned int uint
Definition: qglobal.h:334
unsigned char quint8
Definition: qglobal.h:284
#define qDebug
[1]
Definition: qlogging.h:177
#define qWarning
Definition: qlogging.h:179
#define qFatal
Definition: qlogging.h:181
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLfloat GLfloat GLfloat w
[0]
GLenum GLuint GLintptr offset
GLuint name
GLdouble s
[6]
Definition: qopenglext.h:235
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
#define QStringLiteral(str)
QFile file
[0]
view viewport() -> scroll(dx, dy, deviceRect)
bool contains(const AT &t) const noexcept
Definition: qlist.h:78
QWindow * m_window
Definition: main.mm:56