Как реализовать правило трех для объектов Vulkan?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Как реализовать правило трех для объектов Vulkan?

Сообщение Anonymous »

Мне хотелось бы создавать простые векторы шейдеров, конвейеров, текстур и других объектов, используемых с API Vulkan, но я не могу понять, как использовать конструкторы копирования, конструкторы перемещения, операции копирования-назначения и перемещения-назначения.
Моя программа создает вектор шейдерных структур для передачи в конвейер для создания:

Код: Выделить всё

std::vector testShaders{
{"vertex.vert", VK_SHADER_STAGE_VERTEX_BIT},
{"vertex.frag", VK_SHADER_STAGE_FRAGMENT_BIT}
};
vk::GraphicsPPL testPPL(testShaders);
Приведенный выше метод возвращает ошибку уровня проверки, где модули шейдера имеют значение VK_NULL_HANDLE. В другом вопросе о переполнении стека решение загрузки векторов заключалось в реализации правила трех, но сейчас я пытаюсь понять, как это сделать, не вызывая других ошибок. Я предпринял несколько попыток создать оператор копирования-присвоения и конструктор копирования, используя справочную страницу cpp, но, похоже, мне не удалось избежать сбоя моей программы. Вот некоторые из моих попыток:

Код: Выделить всё

Shader(const Shader& other) // First attempt: copy constructor
{
std::memcpy(this, other.shaderModule, sizeof(other.shaderModule));
}// exited with code -1073741819.

Shader(const Shader& other) // Second attempt
{
vkDestroyShaderModule(GPU::device, shaderModule, nullptr);
//delete[] shaderModule; //With or without, does not change the outcome

std::memcpy(shaderModule, other.shaderModule, sizeof(other.shaderModule));
} // Couldn't find VkShaderModule Object 0xcdcdcdcdcdcdcdcd and VK_NULL_HANDLE

/* Third attempt */
Shader(const Shader& other)
: shaderStage(other.shaderStage){}

Shader& operator=(const Shader& other) // III.  copy assignment
{
if (this == &other)
return *this;

VkShaderModule new_shaderModule{};
//sizeof(new_shaderModule) returns 8
//sizeof(other.shaderModule) returns 8
std::memcpy(new_shaderModule, other.shaderModule, sizeof(other.shaderModule));
vkDestroyShaderModule(GPU::device, shaderModule, nullptr); // No difference with or without, neither replacing or adding "delete[] shaderModule"
shaderModule = new_shaderModule;

return *this;
}// VK_NULL_HANDLE error

Shader(const Shader& other) // Fourth attempt - forgot to add this one
{
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"); // Function omitted from post for brevity, please don't hesitate to ask if needed
createShaderModule(code, filename);
}
~Shader() {
vkDestroyShaderModule(GPU::device, shaderModule, nullptr);
// Delete[] shaderModule // With or without, did not change the outcome
}
void createShaderModule(const std::vector& code, const std::string& filename) {
VkShaderModuleCreateInfo createInfo
{ VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO };
createInfo.codeSize = code.size();
createInfo.pCode = reinterpret_cast(code.data());

if (vkCreateShaderModule(GPU::device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
throw std::runtime_error("failed to create " + filename + "!");
}
}
/* My failed attempts here */
}
На всякий случай, вот как 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 // move constructor
: shaderModule(std::exchange(other.shaderModule, nullptr)), shaderStage(std::exchange(other.shaderStage, nullptr)) {}

Shader& operator=(Shader&& other) noexcept // move assignment
{
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 // move constructor
{
std::swap(*this, other);
// std::exchange(*this, other); // no dice either
}

Shader& operator=(Shader&& other) noexcept // move assignment
{
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
Я попробовал решение SharModule(nullptr) в дополнение к закомментированию двух строк удаления без разницы в ошибке.

Подробнее здесь: https://stackoverflow.com/questions/771 ... an-objects
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»