Vulkan的VkImageView和VkImage对象在SwapChain中造成了未处理的excption。

问题描述 投票:0回答:1

我在关注 vulkan-tutorial 而我已经成功地渲染了一个旋转的方块。我现在正处于课程中应用纹理之前的阶段。在课程内继续之前,我一直在将代码模块化,一次一个接口框架。我已经成功地将各种Vulkan对象从主引擎类中提取出来,变成自己的类。这些类的每个对象都有一个接口,至少有一个初始化、创建和清理功能。

我已经用一个Buffer类完成了这个工作,它是一个抽象的基类,我的IndexBuffer、VertexBuffer和UniformBuffer都是由它派生出来的。我已经用我的CommandPool类、SyncObjects(VkSemaphore和VkFence)类、我的Pipelines(目前只有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!");
        }
    }
}

在这种状态下,我的代码一切都很正常。我能够渲染一个旋转的彩色方块,我可以调整窗口的大小并关闭窗口,从Visual Studio和Vulkan Layers都没有出现错误。


当我改成我之前做过的这种模式。

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类中的 "this "指针是... ... 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()我试过通过复制、引用、指针、const reference、const pointer等方式传递参数,但无济于事,以上方式都没有用。所有的东西都一直引起异常。我不知道是什么原因导致了访问违规。由于某种原因,ImageView类没有正确地分配内存给 image_ 委员,因为它指出: thisnullptr 的类,或者它不能写入内存等等。然而,我对所有其他Vulkan对象都遵循同样的模式,直到现在才发现这个问题。

VkImageView和VkImage在SwapChain中的用法和正确设置是什么?目前,VkImageView和VkImage在SwapChain中的使用和正确设置是怎样的?VkImage在 SwapChain 中仍然以下列形式存储着 std::vector<VkImage> 我可以直接在类内成功创建它,但是当我试图将VkImageView提取出来变成自己的类对象时,我就开始遇到这个问题。我正在通过这个教程学习Vulkan,我开始掌握它是如何设计的,但我仍然不是API专家。现在,任何帮助都将被感激。而且,是的,我已经通过调试器,我已经观察了我的变量,我已经观察了调用堆栈,我的生活,我完全被绊倒了。如果你需要更多的信息,请不要犹豫地问。

c++ c++17 access-violation vulkan unhandled-exception
1个回答
0
投票

用户 尼古拉斯 在评论区指出,我已经 i = std::shared_ptr<ImageView>() 而我应该有 i = std::make_shared<ImageView>() 是的,这是正确的,我的其他独立类也是这样创建的。这是一个被忽略的打字错误。所以我把功劳归于 NicolBolas 为的。然而,在修复了这个bug之后,它让我找到并修复了真正的bug。

真正的bug是导致 Unhandled Exception 毫无关系 ImageView, VkImageView, VkImage 对象。真正的罪魁祸首是在 ImageView 类本身在其 initialize() 方法。我是将其成员 device_ 范围内的if语句,我在检查是否有 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;
}

现在代码又开始工作了,我有一个旋转的彩色方块。代码退出时没有出现任何错误,Vulkan Layers也没有任何消息。

我只是忽略了 {} 在函数的if语句中。

© www.soinside.com 2019 - 2024. All rights reserved.