I am a beginner in Vulkan, learning Vulkan based on Qt
I want to copy the graphics from the memory to the GPU memory and display it, but there is a QVulkanWindow: Device lost error. Hope to get an answer.
The following is the complete code:
qt_vulkan_test.tar.gz (8.0 KB)
main.c
#include "VulkanWindow.h"
#include <QGuiApplication>
#include <QVulkanInstance>
#include <QLoggingCategory>
int main(int argc, char *argv[])
{
QGuiApplication a(argc, argv);
QLoggingCategory::setFilterRules(QStringLiteral("qt.vulkan=true"));
QVulkanInstance inst;
inst.setLayers(QByteArrayList() <<
"VK_LAYER_GOOGLE_threading" <<
"VK_LAYER_LUNARG_parameter_validation" <<
"VK_LAYER_LUNARG_object_tracker" <<
"VK_LAYER_LUNARG_core_validation" <<
"VK_LAYER_LUNARG_image" <<
"VK_LAYER_LUNARG_swapchain" <<
"VK_LAYER_GOOGLE_unique_objects");
if (!inst.create())
{
qFatal("无法创建Vulkan实例: %d", inst.errorCode());
}
VulkanWindow w;
w.setVulkanInstance(&inst);
w.resize(1024, 768);
w.show();
return a.exec();
}
VulkanWindow.h
#ifndef VULKANWINDOW_H
#define VULKANWINDOW_H
#include <QVulkanWindow>
class VulkanRenderer : public QVulkanWindowRenderer
{
public:
VulkanRenderer(QVulkanWindow *w, bool msaa = false);
void initResources() override;
void initSwapChainResources() override;
void releaseSwapChainResources() override;
void releaseResources() override;
void startNextFrame() override;
void prepareVertices(const int concurrentFrameCount, bool useStagingBuffers);
void setupDescriptorPool(const int concurrentFrameCount);
void setupDescriptorSetLayout();
void preparePipelines();
void setupDescriptorSet(const int concurrentFrameCount);
uint32_t getMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties);
void flushCommandBuffer(VkCommandPool cmdPool, VkCommandBuffer commandBuffer);
protected:
VkShaderModule createShader(const QString &name);
QVulkanWindow *m_window;
VkDevice dev;
QVulkanFunctions *m_funcs;
QVulkanDeviceFunctions *m_devFuncs;
VkDeviceMemory m_bufMem = VK_NULL_HANDLE;
VkBuffer m_buf = VK_NULL_HANDLE;
VkDescriptorBufferInfo m_uniformBufInfo[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT];
VkCommandBuffer cmdBuffer;
VkDescriptorPool m_descPool = VK_NULL_HANDLE;
VkDescriptorSetLayout m_descSetLayout = VK_NULL_HANDLE;
VkDescriptorSet m_descSet[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT];
VkPipelineCache m_pipelineCache = VK_NULL_HANDLE;
VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
VkPipeline m_pipeline = VK_NULL_HANDLE;
uint32_t indexBufferSize;
QMatrix4x4 m_proj;
float m_rotation = 0.0f;
};
class VulkanWindow : public QVulkanWindow
{
Q_OBJECT
public:
QVulkanWindowRenderer *createRenderer() override;
};
#endif // VULKANWINDOW_H
VulkanWindow.cpp
#include "VulkanWindow.h"
#include <QVulkanFunctions>
#include <QFile>
#define DEFAULT_FENCE_TIMEOUT 100000000000
QVulkanWindowRenderer *VulkanWindow::createRenderer()
{
return new VulkanRenderer(this, true);
}
static const int UNIFORM_DATA_SIZE = 16 * sizeof(float);
static inline VkDeviceSize aligned(VkDeviceSize v, VkDeviceSize byteAlign)
{
return (v + byteAlign - 1) & ~(byteAlign - 1);
}
VulkanRenderer::VulkanRenderer(QVulkanWindow *w, bool msaa)
: m_window(w)
{
if (msaa)
{
const QVector<int> counts = w->supportedSampleCounts();
for (int s = 16; s >= 4; s /= 2)
{
if (counts.contains(s))
{
m_window->setSampleCount(s);
break;
}
}
}
}
VkShaderModule VulkanRenderer::createShader(const QString &name)
{
QFile file(name);
if (!file.open(QIODevice::ReadOnly))
{
return VK_NULL_HANDLE;
}
QByteArray blob = file.readAll();
file.close();
VkShaderModuleCreateInfo shaderInfo;
memset(&shaderInfo, 0, sizeof(shaderInfo));
shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
shaderInfo.codeSize = blob.size();
shaderInfo.pCode = reinterpret_cast<const uint32_t *>(blob.constData());
VkShaderModule shaderModule;
VkResult err = m_devFuncs->vkCreateShaderModule(m_window->device(), &shaderInfo, nullptr, &shaderModule);
if (err != VK_SUCCESS)
{
return VK_NULL_HANDLE;
}
return shaderModule;
}
void VulkanRenderer::initResources()
{
const int concurrentFrameCount = m_window->concurrentFrameCount();
dev = m_window->device();
m_funcs = m_window->vulkanInstance()->functions();
m_devFuncs = m_window->vulkanInstance()->deviceFunctions(dev);
prepareVertices(concurrentFrameCount, true);
setupDescriptorSetLayout();
preparePipelines();
setupDescriptorPool(concurrentFrameCount);
setupDescriptorSet(concurrentFrameCount);
}
void VulkanRenderer::initSwapChainResources()
{
m_proj = m_window->clipCorrectionMatrix();
const QSize sz = m_window->swapChainImageSize();
m_proj.perspective(45.0f, sz.width() / (float) sz.height(), 0.01f, 100.0f);
m_proj.translate(0, 0, -4);
}
void VulkanRenderer::releaseSwapChainResources()
{
}
void VulkanRenderer::releaseResources()
{
VkDevice dev = m_window->device();
if (m_pipeline)
{
m_devFuncs->vkDestroyPipeline(dev,
m_pipeline,
nullptr);
m_pipeline = VK_NULL_HANDLE;
}
if (m_pipelineLayout)
{
m_devFuncs->vkDestroyPipelineLayout(dev,
m_pipelineLayout,
nullptr);
m_pipelineLayout = VK_NULL_HANDLE;
}
if (m_pipelineCache)
{
m_devFuncs->vkDestroyPipelineCache(dev, m_pipelineCache, nullptr);
m_pipelineCache = VK_NULL_HANDLE;
}
if (m_descSetLayout)
{
m_devFuncs->vkDestroyDescriptorSetLayout(dev, m_descSetLayout, nullptr);
m_descSetLayout = VK_NULL_HANDLE;
}
if (m_descPool)
{
m_devFuncs->vkDestroyDescriptorPool(dev, m_descPool, nullptr);
m_descPool = VK_NULL_HANDLE;
}
if (m_buf)
{
m_devFuncs->vkDestroyBuffer(dev, m_buf, nullptr);
m_buf = VK_NULL_HANDLE;
}
if (m_bufMem)
{
m_devFuncs->vkFreeMemory(dev, m_bufMem, nullptr);
m_bufMem = VK_NULL_HANDLE;
}
}
void VulkanRenderer::startNextFrame()
{
VkCommandBuffer cmdBuf = m_window->currentCommandBuffer();
const QSize sz = m_window->swapChainImageSize();
VkClearColorValue clearColor =
{
{ 0, 0, 0, 1 }
};
VkClearDepthStencilValue clearDS =
{
1,
0
};
VkClearValue clearValues[3];
memset(clearValues, 0, sizeof(clearValues));
clearValues[0].color = clearColor;
clearValues[2].color = clearColor;
clearValues[1].depthStencil = clearDS;
VkRenderPassBeginInfo rpBeginInfo;
memset(&rpBeginInfo, 0, sizeof(rpBeginInfo));
rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
rpBeginInfo.renderPass = m_window->defaultRenderPass();
rpBeginInfo.framebuffer = m_window->currentFramebuffer();
rpBeginInfo.renderArea.extent.width = sz.width();
rpBeginInfo.renderArea.extent.height = sz.height();
rpBeginInfo.clearValueCount = m_window->sampleCountFlagBits() > VK_SAMPLE_COUNT_1_BIT ? 3 : 2;
rpBeginInfo.pClearValues = clearValues;
m_devFuncs->vkCmdBeginRenderPass(cmdBuf,
&rpBeginInfo,
VK_SUBPASS_CONTENTS_INLINE);
//quint8 *p;
//VkResult err = m_devFuncs->vkMapMemory(dev,
// m_bufMem,
// m_uniformBufInfo[m_window->currentFrame()].offset,
// UNIFORM_DATA_SIZE,
// 0,
// reinterpret_cast<void **>(&p));
//if (err != VK_SUCCESS)
//{
// qFatal("映射内存失败1: %d", err);
//}
//QMatrix4x4 m = m_proj;
//m.rotate(m_rotation, 0, 1, 0);
//memcpy(p, m.constData(), 16 * sizeof(float));
//m_devFuncs->vkUnmapMemory(dev, m_bufMem);
//m_rotation += 1.0f;
VkViewport viewport;
viewport.x = viewport.y = 0;
viewport.width = sz.width();
viewport.height = sz.height();
viewport.minDepth = 0;
viewport.maxDepth = 1;
m_devFuncs->vkCmdSetViewport(cmdBuf,
0,
1,
&viewport);
VkRect2D scissor;
scissor.offset.x = 0;
scissor.offset.y = 0;
scissor.extent.width = viewport.width;
scissor.extent.height = viewport.height;
m_devFuncs->vkCmdSetScissor(cmdBuf,
0,
1,
&scissor);
m_devFuncs->vkCmdBindDescriptorSets(cmdBuf,
VK_PIPELINE_BIND_POINT_GRAPHICS,
m_pipelineLayout,
0,
1,
&m_descSet[m_window->currentFrame()],
0,
nullptr);
m_devFuncs->vkCmdBindPipeline(cmdBuf,
VK_PIPELINE_BIND_POINT_GRAPHICS,
m_pipeline);
VkDeviceSize vbOffset = 0;
m_devFuncs->vkCmdBindVertexBuffers(cmdBuf,
0,
1,
&m_buf,
&vbOffset);
m_devFuncs->vkCmdBindIndexBuffer(cmdBuf, m_buf, 0, VK_INDEX_TYPE_UINT32);
m_devFuncs->vkCmdDrawIndexed(cmdBuf, indexBufferSize, 1, 0, 0, 1);
//m_devFuncs->vkCmdDraw(cmdBuffer, // 记录命令的命令缓冲区
// 3, // 要绘制的顶点数
// 1, // 要绘制的实例数
// 0, // 要绘制的第一个顶点的索引
// 0); // 要绘制的第一个实例的实例 ID
m_devFuncs->vkCmdEndRenderPass(cmdBuf);
m_window->frameReady();
m_window->requestUpdate();
}
void VulkanRenderer::prepareVertices(const int concurrentFrameCount,
bool useStagingBuffers)
{
static float vertexData[] =
{
0.0f, 0.5f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.0f, 0.0f, 1.0f
};
const VkPhysicalDeviceLimits *pdevLimits = &m_window->physicalDeviceProperties()->limits;
const VkDeviceSize uniAlign = pdevLimits->minUniformBufferOffsetAlignment;
const VkDeviceSize vertexAllocSize = aligned(sizeof(vertexData), uniAlign);
const VkDeviceSize uniformAllocSize = aligned(UNIFORM_DATA_SIZE, uniAlign);
indexBufferSize = vertexAllocSize + concurrentFrameCount * uniformAllocSize;
if (useStagingBuffers)
{
VkBuffer host_buf = VK_NULL_HANDLE;
VkDeviceMemory host_bufMem = VK_NULL_HANDLE;
VkBufferCreateInfo bufInfo;
memset(&bufInfo, 0, sizeof(bufInfo));
bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufInfo.size = indexBufferSize;
bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
VkResult err = m_devFuncs->vkCreateBuffer(dev,
&bufInfo,
nullptr,
&host_buf);
if (err != VK_SUCCESS)
{
qFatal("创建缓冲区失败: %d", err);
}
VkMemoryRequirements memReq;
m_devFuncs->vkGetBufferMemoryRequirements(dev,
host_buf,
&memReq);
VkMemoryAllocateInfo memAllocInfo;
memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
memAllocInfo.pNext = nullptr,
memAllocInfo.allocationSize = memReq.size,
//memAllocInfo.memoryTypeIndex = getMemoryTypeIndex(memReq.memoryTypeBits,
// VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
memAllocInfo.memoryTypeIndex = m_window->hostVisibleMemoryIndex();
err = m_devFuncs->vkAllocateMemory(dev,
&memAllocInfo,
nullptr,
&host_bufMem);
if (err != VK_SUCCESS)
{
qFatal("分配内存失败: %d", err);
}
void *data;
err = m_devFuncs->vkMapMemory(dev,
host_bufMem,
0,
memReq.size,
0,
&data);
if (err != VK_SUCCESS)
{
qFatal("映射内存失败: %d", err);
}
memcpy(data, vertexData, sizeof(vertexData));
QMatrix4x4 ident;
memset(m_uniformBufInfo, 0, sizeof(m_uniformBufInfo));
for (int i = 0; i < concurrentFrameCount; ++i)
{
const VkDeviceSize offset = vertexAllocSize + i * uniformAllocSize;
memcpy(data + offset,
ident.constData(),
16 * sizeof(float));
m_uniformBufInfo[i].buffer = host_buf;
m_uniformBufInfo[i].offset = offset;
m_uniformBufInfo[i].range = uniformAllocSize;
}
m_devFuncs->vkUnmapMemory(dev,
host_bufMem);
err = m_devFuncs->vkBindBufferMemory(dev,
host_buf,
host_bufMem,
0);
if (err != VK_SUCCESS)
{
qFatal("绑定缓冲内存失败: %d", err);
}
bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
err = m_devFuncs->vkCreateBuffer(dev,
&bufInfo,
nullptr,
&m_buf);
if (err != VK_SUCCESS)
{
qFatal("创建缓冲区失败: %d", err);
}
m_devFuncs->vkGetBufferMemoryRequirements(dev,
m_buf,
&memReq);
memAllocInfo.allocationSize = memReq.size;
memAllocInfo.memoryTypeIndex = getMemoryTypeIndex(memReq.memoryTypeBits,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
err = m_devFuncs->vkAllocateMemory(dev,
&memAllocInfo,
nullptr,
&m_bufMem);
if (err != VK_SUCCESS)
{
qFatal("分配内存失败: %d", err);
}
err = m_devFuncs->vkBindBufferMemory(dev,
m_buf,
m_bufMem,
0);
if (err != VK_SUCCESS)
{
qFatal("绑定缓冲内存失败: %d", err);
}
VkCommandPool cmdPool;
VkCommandPoolCreateInfo cmdPoolInfo = {};
cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
cmdPoolInfo.queueFamilyIndex = m_window->graphicsQueueFamilyIndex();
cmdPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
err = m_devFuncs->vkCreateCommandPool(dev, &cmdPoolInfo, nullptr, &cmdPool);
if (err != VK_SUCCESS)
{
qFatal("创建命令池失败: %d", err);
}
VkCommandBufferAllocateInfo cmdBufAllocateInfo = {};
cmdBufAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
cmdBufAllocateInfo.commandPool = cmdPool;
cmdBufAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
cmdBufAllocateInfo.commandBufferCount = 1;
err = m_devFuncs->vkAllocateCommandBuffers(dev, &cmdBufAllocateInfo, &cmdBuffer);
if (err != VK_SUCCESS)
{
qFatal("分配命令缓冲区失败: %d", err);
}
//cmdBuffer = m_window->currentCommandBuffer();
VkCommandBufferBeginInfo cmdBufInfo = {};
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
cmdBufInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
err = m_devFuncs->vkBeginCommandBuffer(cmdBuffer, &cmdBufInfo);
if (err != VK_SUCCESS)
{
qFatal("将命令记录到命令缓冲区中失败: %d", err);
}
VkBufferCopy copyRegion = {};
copyRegion.size = sizeof(m_uniformBufInfo);
m_devFuncs->vkCmdCopyBuffer(cmdBuffer, host_buf, m_buf, 1, ©Region);
flushCommandBuffer(cmdPool, cmdBuffer);
m_devFuncs->vkDestroyBuffer(dev, host_buf, nullptr);
m_devFuncs->vkFreeMemory(dev, host_bufMem, nullptr);
}
else
{
VkBufferCreateInfo bufInfo;
memset(&bufInfo, 0, sizeof(bufInfo));
bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufInfo.size = vertexAllocSize + concurrentFrameCount * uniformAllocSize;
bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
VkResult err = m_devFuncs->vkCreateBuffer(dev,
&bufInfo,
nullptr,
&m_buf);
if (err != VK_SUCCESS)
{
qFatal("创建缓冲区失败: %d", err);
}
VkMemoryRequirements memReq;
m_devFuncs->vkGetBufferMemoryRequirements(dev,
m_buf,
&memReq);
VkMemoryAllocateInfo memAllocInfo = {
VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
nullptr,
memReq.size,
m_window->hostVisibleMemoryIndex()
};
err = m_devFuncs->vkAllocateMemory(dev,
&memAllocInfo,
nullptr,
&m_bufMem);
if (err != VK_SUCCESS)
{
qFatal("分配内存失败: %d", err);
}
quint8 *p;
err = m_devFuncs->vkMapMemory(dev,
m_bufMem,
0,
memReq.size,
0,
reinterpret_cast<void **>(&p));
if (err != VK_SUCCESS)
{
qFatal("映射内存失败: %d", err);
}
memcpy(p, vertexData, sizeof(vertexData));
QMatrix4x4 ident;
memset(m_uniformBufInfo, 0, sizeof(m_uniformBufInfo));
for (int i = 0; i < concurrentFrameCount; ++i)
{
const VkDeviceSize offset = vertexAllocSize + i * uniformAllocSize;
memcpy(p + offset,
ident.constData(),
16 * sizeof(float));
m_uniformBufInfo[i].buffer = m_buf;
m_uniformBufInfo[i].offset = offset;
m_uniformBufInfo[i].range = uniformAllocSize;
}
m_devFuncs->vkUnmapMemory(dev,
m_bufMem);
err = m_devFuncs->vkBindBufferMemory(dev,
m_buf,
m_bufMem,
0);
if (err != VK_SUCCESS)
{
qFatal("绑定缓冲内存失败: %d", err);
}
}
}
void VulkanRenderer::setupDescriptorPool(const int concurrentFrameCount)
{
VkDescriptorPoolSize descPoolSizes =
{
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
uint32_t(concurrentFrameCount)
};
VkDescriptorPoolCreateInfo descPoolInfo;
memset(&descPoolInfo, 0, sizeof(descPoolInfo));
descPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
descPoolInfo.maxSets = concurrentFrameCount;
descPoolInfo.poolSizeCount = 1;
descPoolInfo.pPoolSizes = &descPoolSizes;
VkResult err = m_devFuncs->vkCreateDescriptorPool(dev,
&descPoolInfo,
nullptr,
&m_descPool);
if (err != VK_SUCCESS)
{
qFatal("未能创建描述符池: %d", err);
}
}
void VulkanRenderer::setupDescriptorSetLayout()
{
VkDescriptorSetLayoutBinding layoutBinding = {
0,
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
1,
VK_SHADER_STAGE_VERTEX_BIT,
nullptr
};
VkDescriptorSetLayoutCreateInfo descLayoutInfo =
{
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
nullptr,
0,
1,
&layoutBinding
};
VkResult err = m_devFuncs->vkCreateDescriptorSetLayout(dev,
&descLayoutInfo,
nullptr,
&m_descSetLayout);
if (err != VK_SUCCESS)
{
qFatal("无法创建描述符集布局: %d", err);
}
VkPipelineLayoutCreateInfo pipelineLayoutInfo;
memset(&pipelineLayoutInfo, 0, sizeof(pipelineLayoutInfo));
pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipelineLayoutInfo.setLayoutCount = 1;
pipelineLayoutInfo.pSetLayouts = &m_descSetLayout;
err = m_devFuncs->vkCreatePipelineLayout(dev,
&pipelineLayoutInfo,
nullptr,
&m_pipelineLayout);
if (err != VK_SUCCESS)
{
qFatal("未能创建管线布局: %d", err);
}
}
void VulkanRenderer::preparePipelines()
{
VkVertexInputBindingDescription vertexBindingDesc =
{
0,
5 * sizeof(float),
VK_VERTEX_INPUT_RATE_VERTEX
};
VkVertexInputAttributeDescription vertexAttrDesc[] =
{
{
0,
0,
VK_FORMAT_R32G32_SFLOAT,
0
},
{
1,
0,
VK_FORMAT_R32G32B32_SFLOAT,
2 * sizeof(float)
}
};
VkPipelineVertexInputStateCreateInfo vertexInputInfo;
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.pNext = nullptr;
vertexInputInfo.flags = 0;
vertexInputInfo.vertexBindingDescriptionCount = 1;
vertexInputInfo.pVertexBindingDescriptions = &vertexBindingDesc;
vertexInputInfo.vertexAttributeDescriptionCount = 2;
vertexInputInfo.pVertexAttributeDescriptions = vertexAttrDesc;
VkPipelineCacheCreateInfo pipelineCacheInfo;
memset(&pipelineCacheInfo, 0, sizeof(pipelineCacheInfo));
pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
VkResult err = m_devFuncs->vkCreatePipelineCache(dev,
&pipelineCacheInfo,
nullptr,
&m_pipelineCache);
if (err != VK_SUCCESS)
{
qFatal("无法创建管线缓存: %d", err);
}
VkShaderModule vertShaderModule = createShader(QStringLiteral(":/Vulkan_Triangle/color_vert.spv"));
VkShaderModule fragShaderModule = createShader(QStringLiteral(":/Vulkan_Triangle/color_frag.spv"));
VkGraphicsPipelineCreateInfo pipelineInfo;
memset(&pipelineInfo, 0, sizeof(pipelineInfo));
pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
VkPipelineShaderStageCreateInfo shaderStages[2] =
{
{
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
nullptr,
0,
VK_SHADER_STAGE_VERTEX_BIT,
vertShaderModule,
"main",
nullptr
},
{
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
nullptr,
0,
VK_SHADER_STAGE_FRAGMENT_BIT,
fragShaderModule,
"main",
nullptr
}
};
pipelineInfo.stageCount = 2;
pipelineInfo.pStages = shaderStages;
pipelineInfo.pVertexInputState = &vertexInputInfo;
VkPipelineInputAssemblyStateCreateInfo ia;
memset(&ia, 0, sizeof(ia));
ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
pipelineInfo.pInputAssemblyState = &ia;
VkPipelineViewportStateCreateInfo vp;
memset(&vp, 0, sizeof(vp));
vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
vp.viewportCount = 1;
vp.scissorCount = 1;
pipelineInfo.pViewportState = &vp;
VkPipelineRasterizationStateCreateInfo rs;
memset(&rs, 0, sizeof(rs));
rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rs.polygonMode = VK_POLYGON_MODE_FILL;
rs.cullMode = VK_CULL_MODE_NONE;
rs.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
rs.lineWidth = 1.0f;
pipelineInfo.pRasterizationState = &rs;
VkPipelineMultisampleStateCreateInfo ms;
memset(&ms, 0, sizeof(ms));
ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
ms.rasterizationSamples = m_window->sampleCountFlagBits();
pipelineInfo.pMultisampleState = &ms;
VkPipelineDepthStencilStateCreateInfo ds;
memset(&ds, 0, sizeof(ds));
ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
ds.depthTestEnable = VK_TRUE;
ds.depthWriteEnable = VK_TRUE;
ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
pipelineInfo.pDepthStencilState = &ds;
VkPipelineColorBlendStateCreateInfo cb;
memset(&cb, 0, sizeof(cb));
cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
VkPipelineColorBlendAttachmentState att;
memset(&att, 0, sizeof(att));
att.colorWriteMask = 0xF;
cb.attachmentCount = 1;
cb.pAttachments = &att;
pipelineInfo.pColorBlendState = &cb;
VkDynamicState dynEnable[] =
{
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
};
VkPipelineDynamicStateCreateInfo dyn;
memset(&dyn, 0, sizeof(dyn));
dyn.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dyn.dynamicStateCount = sizeof(dynEnable) / sizeof(VkDynamicState);
dyn.pDynamicStates = dynEnable;
pipelineInfo.pDynamicState = &dyn;
pipelineInfo.layout = m_pipelineLayout;
pipelineInfo.renderPass = m_window->defaultRenderPass();
err = m_devFuncs->vkCreateGraphicsPipelines(dev,
m_pipelineCache,
1,
&pipelineInfo,
nullptr,
&m_pipeline);
if (err != VK_SUCCESS)
{
qFatal("未能创建图形管线: %d", err);
}
if (vertShaderModule)
{
m_devFuncs->vkDestroyShaderModule(dev,
vertShaderModule,
nullptr);
}
if (fragShaderModule)
{
m_devFuncs->vkDestroyShaderModule(dev, fragShaderModule, nullptr);
}
}
void VulkanRenderer::setupDescriptorSet(const int concurrentFrameCount)
{
for (int i = 0; i < concurrentFrameCount; ++i)
{
VkDescriptorSetAllocateInfo descSetAllocInfo = {
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
nullptr,
m_descPool,
1,
&m_descSetLayout
};
VkResult err = m_devFuncs->vkAllocateDescriptorSets(dev,
&descSetAllocInfo,
&m_descSet[i]);
if (err != VK_SUCCESS)
{
qFatal("分配描述符集失败: %d", err);
}
VkWriteDescriptorSet descWrite;
memset(&descWrite, 0, sizeof(descWrite));
descWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descWrite.dstSet = m_descSet[i];
descWrite.descriptorCount = 1;
descWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descWrite.pBufferInfo = &m_uniformBufInfo[i];
m_devFuncs->vkUpdateDescriptorSets(dev,
1,
&descWrite,
0,
nullptr);
}
}
uint32_t VulkanRenderer::getMemoryTypeIndex(uint32_t typeBits,
VkMemoryPropertyFlags properties)
{
VkPhysicalDeviceMemoryProperties deviceMemoryProperties;
m_funcs->vkGetPhysicalDeviceMemoryProperties(m_window->physicalDevice(),
&deviceMemoryProperties);
for (uint32_t i = 0; i < deviceMemoryProperties.memoryTypeCount; i++)
{
if ((typeBits & 1) == 1)
{
if ((deviceMemoryProperties.memoryTypes[i].propertyFlags & properties) == properties)
{
return i;
}
}
typeBits >>= 1;
}
throw "找不到合适的内存类型!";
}
void VulkanRenderer::flushCommandBuffer(VkCommandPool cmdPool,
VkCommandBuffer commandBuffer)
{
assert(commandBuffer != VK_NULL_HANDLE);
VkResult err = m_devFuncs->vkEndCommandBuffer(commandBuffer);
if (err != VK_SUCCESS)
{
qFatal("结束命令缓冲区记录失败: %d", err);
}
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffer;
VkFenceCreateInfo fenceCreateInfo = {};
fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceCreateInfo.flags = 0;
VkFence fence;
err = m_devFuncs->vkCreateFence(dev, &fenceCreateInfo, nullptr, &fence);
if (err != VK_SUCCESS)
{
qFatal("创建栅栏失败: %d", err);
}
VkQueue queue;
m_devFuncs->vkGetDeviceQueue(dev, m_window->graphicsQueueFamilyIndex(), 0, &queue);
err = m_devFuncs->vkQueueSubmit(queue, 1, &submitInfo, fence);
if (err != VK_SUCCESS)
{
qFatal("栅栏提交到队列失败: %d", err);
}
err = m_devFuncs->vkWaitForFences(dev, 1, &fence, VK_TRUE, DEFAULT_FENCE_TIMEOUT);
if (err != VK_SUCCESS)
{
qFatal("等待栅栏发出命令缓冲区已完成执行的信号失败: %d", err);
}
m_devFuncs->vkDestroyFence(dev, fence, nullptr);
m_devFuncs->vkFreeCommandBuffers(dev, cmdPool, 1, &commandBuffer);
}