如何为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
相关产品推荐
相关产品推荐

