Я следую vulkan-tutorial , и я успешно рендерил вращающийся квадрат. Я нахожусь в точке на уроках прямо перед применением текстур. Перед тем, как перейти к урокам, я по отдельности модулировал код в структуру интерфейсов. Мне успешно удалось извлечь различные объекты Vulkan из основного класса движка в их собственные классы. Каждый из этих объектов класса имеет как минимум интерфейс с функциями инициализации, создания и очистки.
Я сделал это с помощью класса Buffer, который является абстрактным базовым классом, из которого все мои IndexBuffer, VertexBuffer и UniformBuffer получены. Я сделал это с помощью моего класса CommandPool, классов SyncObjects (VkSemaphore и VkFence), моих конвейеров (пока только MainGraphicsPipeline) и моего SwapChain.
Со всеми этими в своих собственных классах я сейчас хранение этих классов как shared_ptr<Class>
или vector<shared_ptr<Class>>
в моих классах, которые имеют внутренние экземпляры этих классов. Это поток проектирования, с которым я остался.
Все работало идеально, пока я не начал содержать типы VkImageView
в своем собственном классе. В моем классе SwapChain
он содержал приватный член:
std::vector<VkImageView> imageViews_
и эти функции-члены, которые на них работают:
void SwapChain::cleanupImageViews() {
for (auto imageView : imageViews_) {
vkDestroyImageView(*device_, imageView, nullptr);
}
}
void SwapChain::createImageViews() {
imageViews_.resize(images_.size());
for (size_t i = 0; i < images_.size(); i++) {
VkImageViewCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.image = images_[i];
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = imageFormat_;
createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
createInfo.subresourceRange.baseMipLevel = 0;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.baseArrayLayer = 0;
createInfo.subresourceRange.layerCount = 1;
if (vkCreateImageView(*device_, &createInfo, nullptr, &imageViews_[i]) != VK_SUCCESS) {
throw std::runtime_error("failed to create image views!");
}
}
}
С моим кодом в этом состоянии все работает нормально. Я могу отобразить вращающийся цветной квадрат, я могу изменить размер окна и закрыть окно с 0 ошибками как из Visual Studio, так и из слоев Vulkan.
Когда я переключаюсь на этот шаблон, который я делал ранее:
std::vector<std::shared_ptr<ImageView>> imageViews_;
и мои функции становятся:
void SwapChain::cleanupImageViews() {
for (auto& imageView : imageViews_ ) {
imageView->cleanup();
}
}
void SwapChain::createImageViews() {
imageViews_.resize(images_.size());
for(auto& i : imageViews_) {
i = std::shared_ptr<ImageView>();
i->initialize(device_);
}
for (size_t i = 0; i < images_.size(); i++ ) {
imagesViews_[i]->create(images_[i], imageFormat_);
}
}
Сбой при вызове create () для ImageViews дает мне необработанное исключение: нарушение прав на чтение / запись о том, что указатель «this» в моем классе ImageView равен nullptr
.
Вот как выглядит мой класс ImageView как:
ImageView.h
#pragma once
#include "utility.h"
namespace ForceEngine {
namespace vk {
class ImageView {
private:
VkImageView imageView_;
VkDevice* device_;
VkImage image_;
VkFormat format_;
public:
ImageView() = default;
~ImageView() = default;
void initialize(VkDevice* device);
void create(VkImage image, VkFormat format);
void cleanup();
VkImageView* get() { return &imageView_; }
private:
void createImageView();
};
} // namespace vk
} // namespace ForceEngine
ImageView. cpp
#include "ImageView.h"
namespace ForceEngine {
namespace vk {
void ImageView::initialize(VkDevice* device) {
if (device == nullptr) {
throw std::runtime_error("failed to initialize ImageView: device was nullptr!");
device_ = device;
}
}
void ImageView::create(VkImage image, VkFormat format) {
//if (image == nullptr) throw std::runtime_error("failed to create Image View: image was nullptr!");
//if (format == nullptr) throw std::runtime_error("failed to create Image View: format was nullptr!");
image_ = image; // This is where it is throwing the exception.
format_ = format;
createImageView();
}
void ImageView::createImageView() {
VkImageViewCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.image = image_;
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = format_;
createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
createInfo.subresourceRange.baseMipLevel = 0;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.baseArrayLayer = 0;
createInfo.subresourceRange.layerCount = 1;
if (vkCreateImageView(*device_, &createInfo, nullptr, &imageView_) != VK_SUCCESS) {
throw std::runtime_error("failed to create image views!");
}
}
void ImageView::cleanup() {
vkDestroyImageView(*device_, imageView_, nullptr);
}
} // namespace vk
} // namespace ForceEngine
В пределах мой класс, я попытался иметь image_
в качестве указателя и не указателя и что касается сигнатуры create()
, я попытался передать параметры с помощью копирования, ссылки, указателя, ссылки на констант, указателя константы, и др c. и безрезультатно, ничего из вышеперечисленного не сработало. Все продолжает вызывать исключение. Я не знаю, что является причиной нарушения доступа. По какой-то причине класс ImageView неправильно распределяет память для члена image_
, так как в нем говорится, что this
было nullptr
для этого класса или он не может записывать в память и т. Д. c. Тем не менее, я следовал этому же шаблону для всех других моих объектов Vulkan и до сих пор не имел этой проблемы.
Каковы подходы к использованию и правильной настройке VkImageView и VkImage в контексте контекста SwapChain? В настоящее время VkImage
все еще хранятся в SwapChain как std::vector<VkImage>
. Я могу успешно создать его непосредственно в классе, но когда я пытаюсь извлечь VkImageView из его собственного объекта класса, я начинаю сталкиваться с этой проблемой. , Я изучаю Vulkan через это руководство и начинаю понимать, как он спроектирован, но я все еще не эксперт в API. Прямо сейчас любая помощь будет оценена. И, да, я прошел через отладчик, я посмотрел мои переменные, я наблюдал за стеком вызовов, и на всю жизнь я совершенно ошеломлен. Если вам нужно больше информации, чем это, пожалуйста, не стесняйтесь спрашивать.