繁体   English   中英

Vulkan 的 VkImageView 和 VkImage 对象在 SwapChain 中导致未处理的异常

[英]Vulkan's VkImageView and VkImage objects causing unhandled excecption within the SwapChain

我正在关注vulkan-tutorial并且我已经成功地渲染了一个旋转的正方形。 在应用纹理之前,我正处于课程的重点。 在继续学习课程之前,我一直在将代码模块化成一个接口框架,一次一个。 我已经成功地将各种 Vulkan 对象从主引擎 class 中提取到它们自己的类中。 这些 class 对象中的每一个都具有一个至少具有初始化、创建和清理 function 的接口。

我已经使用缓冲区 class 完成了这项工作,它是一个抽象基础 class,我的 IndexBuffer、VertexBuffer 和 UniformBuffer 都来自该基础。 我已经使用我的 CommandPool class、SyncObjects(VkSemaphore 和 VkFence)类、我的管道(目前只有 MainGraphicsPipeline)和我的 SwapChain 完成了这项工作。

所有这些都在他们自己的类中,我现在将这些类存储为shared_ptr<Class>vector<shared_ptr<Class>>在我的类中,这些类具有这些的内部实例。 这是我一直坚持的设计流程。

在我开始将VkImageView类型包含在它们自己的 class 中之前,一切都运行良好。 在我的SwapChain class 它包含私有成员:

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

使用我在此 state 中的代码,一切正常。 我能够渲染一个旋转的彩色方块,我可以调整 window 的大小并关闭 window,Visual Studio 和 Vulkan 层均出现 0 个错误。


当我更改为以前做过的这种模式时:

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

它在调用 ImageViews 的 create() 时失败,给了我一个未处理的异常:访问读/写冲突,指出我的 ImageView class 中的“this”指针是nullptr


这是我的 ImageView class 的样子:

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

在我的 class 中,我尝试将image_作为指针和非指针,至于create()的签名,我尝试通过复制、引用、指针、常量引用、常量指针等传递参数. 无济于事,以上都没有奏效。 一切都会导致异常。 我不知道是什么导致了访问冲突。 For some reason, the ImageView class is not properly allocating memory for the image_ member as it states that this was nullptr for this class or it can't write to memory, etc. Yet, I've followed this same pattern for all of my其他 Vulkan 对象,直到现在都没有这个问题。

在 SwapChain 的上下文中,VkImageView 和 VkImage 的用法和正确设置是什么? 目前, VkImage仍然作为std::vector<VkImage>存储在 SwapChain 中,我可以直接在 class 中成功创建它,但是当我尝试将 VkImageView 提取到它自己的 class ZA8CFDE68 开始运行到运行时这个问题。 我正在通过本教程学习 Vulkan,并且开始了解它的设计方式,但我仍然不是 API 方面的专家。 现在任何帮助将不胜感激。 而且,是的,我已经通过调试器,我已经观察了我的变量,我已经观察了调用堆栈,而对于我的生活,我完全被难住了。 如果您需要更多信息,请不要犹豫。

用户nicol-bolas在评论部分指出我有i = std::shared_ptr<ImageView>()并且我应该有i = std::make_shared<ImageView>()是的,这是正确的,这就是我的其他独立课程正在创建中。 这是一个被忽视的拼写错误。 因此,我将这一点归功于NicolBolas 但是,在修复了那个错误之后,它让我能够找到并修复真正的错误。

导致Unhandled Exception的实际错误与ImageViewVkImageViewVkImage对象无关。 真正的罪魁祸首是ImageView class 本身在其initialize()方法中。 我在 if 语句的device_中分配了它的成员 device_,我正在检查传入的device指针是否为nullptr

我最初有这个:

void ImageView::initialize(VkDevice* device) {
    if (device == nullptr) { throw std::runtime_error("failed to initialize Image View: device was nullptr!");
        device_ = nullptr;
    }
}

而且device_从未被设置。 它应该是:

void ImageView::initialize(VkDevice* device) {
    if (device == nullptr) throw std::runtime_error("failed to initialize Image View: device was nullptr!");
        device_ = nullptr;
}

现在代码再次工作,我有一个旋转的彩色方块。 代码以 0 个错误退出,并且没有来自 Vulkan 层的消息。

我只是忽略了 function 的 if 语句中的{}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM