QVulkanWindow: Device lost

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, &copyRegion);

        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);
}

Hi user90270,

sorry if I am not able to help immediately, but could you share the exact error message and any log output of your program? Maybe that could give others a bit of a clue what could be the issue here.

Also, what platform are you running on?

  • Hardware specs
  • Operating system
  • Driver version

Thanks!