You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Vulkan对象实现三法则?解决着色器向量创建报错

Vulkan着色器结构体的拷贝与移动语义问题

我想创建存储Vulkan着色器、管线、纹理等对象的std::vector,但在处理拷贝构造函数、移动构造函数、拷贝赋值和移动赋值操作时遇到了困难。

我的程序通过以下方式构建着色器结构体向量并传递给管线创建:

std::vector<vk::Shader> testShaders{
    {"vertex.vert", VK_SHADER_STAGE_VERTEX_BIT},
    {"vertex.frag", VK_SHADER_STAGE_FRAGMENT_BIT}
};
vk::GraphicsPPL<triangleList> testPPL(testShaders);

这会触发验证层错误,提示着色器模块为VK_NULL_HANDLE。参考相关问题后得知需要实现三法则,但尝试实现时不断触发其他错误。我参考cpp-reference编写拷贝赋值运算符和拷贝构造函数,程序总是崩溃,以下是部分尝试代码:

// 第一次尝试:拷贝构造函数
Shader(const Shader& other)
{
    std::memcpy(this, other.shaderModule, sizeof(other.shaderModule));
}// 程序退出码 -1073741819

// 第二次尝试
Shader(const Shader& other)
{
    vkDestroyShaderModule(GPU::device, shaderModule, nullptr);
    //delete[] shaderModule; // 加不加都不影响结果

    std::memcpy(shaderModule, other.shaderModule, sizeof(other.shaderModule));
} // 报错:找不到VkShaderModule对象0xcdcdcdcdcdcdcdcd和VK_NULL_HANDLE

/* 第三次尝试 */
Shader(const Shader& other)
    : shaderStage(other.shaderStage){}

// 拷贝赋值运算符
Shader& operator=(const Shader& other)
{
    if (this == &other)
        return *this;
    
    VkShaderModule new_shaderModule{};
    //sizeof(new_shaderModule) 返回8   
    //sizeof(other.shaderModule) 返回8         
    std::memcpy(new_shaderModule, other.shaderModule, sizeof(other.shaderModule));
    vkDestroyShaderModule(GPU::device, shaderModule, nullptr); // 加不加、替换或添加delete[] shaderModule都无区别
    shaderModule = new_shaderModule;

    return *this;
}// 触发VK_NULL_HANDLE错误

// 第四次尝试
Shader(const Shader& other)
{
    std::memcpy(this, &other, sizeof(Shader));
}

我的着色器结构体定义如下:

struct Shader {
    VkShaderModule shaderModule;
    VkShaderStageFlagBits shaderStage;
    Shader(std::string const& filename, VkShaderStageFlagBits stage)
        : shaderStage(stage)
    {
        auto code = readFile(".\\shaders\\" + filename + ".spv"); // 读取文件函数已省略,需要可提供
        createShaderModule(code, filename);
    }
    ~Shader() {
        vkDestroyShaderModule(GPU::device, shaderModule, nullptr);  
        // Delete[] shaderModule // 加不加都不影响结果
    }
    void createShaderModule(const std::vector<char>& code, const std::string& filename) {
        VkShaderModuleCreateInfo createInfo
        { VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
        createInfo.codeSize = code.size();
        createInfo.pCode = reinterpret_cast<const uint32_t*>(code.data());

        if (vkCreateShaderModule(GPU::device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
            throw std::runtime_error("failed to create " + filename + "!");
        }
    }
    /* 上述失败的尝试代码放在这里 */
};

补充Vulkan的vkCreateShaderModule函数定义:

// Provided by VK_VERSION_1_0
VkResult vkCreateShaderModule(
    VkDevice                                    device,
    const VkShaderModuleCreateInfo*             pCreateInfo,
    const VkAllocationCallbacks*                pAllocator,
    VkShaderModule*                             pShaderModule);

编辑内容:尝试禁用拷贝并实现移动语义

根据建议,我为着色器结构体添加了以下代码:

Shader(const Shader& other) = delete;
Shader& operator=(const Shader& other) = delete;

Shader(Shader&& other) noexcept // 移动构造函数
    : shaderModule(std::exchange(other.shaderModule, nullptr)), shaderStage(std::exchange(other.shaderStage, nullptr)) {}

Shader& operator=(Shader&& other) noexcept // 移动赋值运算符
{
    std::swap(shaderModule, other.shaderModule);
    return *this;
}

但出现新错误:

Error   C2440
'=': cannot convert from 'nullptr' to '_Ty'
/* path */ \MSVC\14.37.32822\include\utility

Error (active) E0304
no instance of function template "std::construct_at" matches the argument list
/* path */ MSVC\14.37.32822\include\xmemory

编辑2:修改移动语义实现

调整移动语义代码如下:

Shader(const Shader& other) = delete;
Shader& operator=(const Shader& other) = delete;

Shader(Shader&& other) noexcept // 移动构造函数
{
    std::swap(*this, other);
    // std::exchange(*this, other); // 同样无效
}

Shader& operator=(Shader&& other) noexcept // 移动赋值运算符
{
    std::swap(*this, other);
    return *this;
}

新错误:

Error   C2280   'vk::Shader::Shader(const vk::Shader &)' 
attempting to reference a deleted function  
/* path */\MSVC\14.37.32822\include\xutility

我尝试过shaderModule(nullptr)的方案,也注释了delete相关代码,但错误依旧。


内容的提问来源于stack exchange,提问作者ModernEraCaveman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 02:36:14