简体   繁体   English

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

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

I'm following vulkan-tutorial and I've successfully rendered a spinning square.我正在关注vulkan-tutorial并且我已经成功地渲染了一个旋转的正方形。 I'm at the point in the lessons right before applying textures.在应用纹理之前,我正处于课程的重点。 Before moving on within the lessons, I've been modularizing the code into a framework of interfaces one piece at a time.在继续学习课程之前,我一直在将代码模块化成一个接口框架,一次一个。 I have successfully managed to extract various Vulkan objects out of the main engine class into their own classes.我已经成功地将各种 Vulkan 对象从主引擎 class 中提取到它们自己的类中。 Each of these class objects has an interface with an initialize, create, and cleanup function at a minimum.这些 class 对象中的每一个都具有一个至少具有初始化、创建和清理 function 的接口。

I've done this with a Buffer class that is an abstract base class that my IndexBuffer, VertexBuffer, and UniformBuffer all derived from.我已经使用缓冲区 class 完成了这项工作,它是一个抽象基础 class,我的 IndexBuffer、VertexBuffer 和 UniformBuffer 都来自该基础。 I've done this with my CommandPool class, SyncObjects(VkSemaphore and VkFence) classes, my Pipelines(only MainGraphicsPipeline for now), and my SwapChain.我已经使用我的 CommandPool class、SyncObjects(VkSemaphore 和 VkFence)类、我的管道(目前只有 MainGraphicsPipeline)和我的 SwapChain 完成了这项工作。

With all of these in their own classes, I'm now storing these classes as either shared_ptr<Class> or vector<shared_ptr<Class>> within my classes that have internal instances of these.所有这些都在他们自己的类中,我现在将这些类存储为shared_ptr<Class>vector<shared_ptr<Class>>在我的类中,这些类具有这些的内部实例。 This is the design flow that I've been staying with.这是我一直坚持的设计流程。

Everything was working perfectly fine until I started to have VkImageView types contained within their own class.在我开始将VkImageView类型包含在它们自己的 class 中之前,一切都运行良好。 Within my SwapChain class it contained the private member:在我的SwapChain class 它包含私有成员:

std::vector<VkImageView> imageViews_ 

and these member functions that work on them:以及对它们起作用的这些成员函数:

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

With my code in this state, everything works fine.使用我在此 state 中的代码,一切正常。 I'm able to render a spinning colored square, I can resize the window and close the window with 0 errors from both Visual Studio and from Vulkan Layers.我能够渲染一个旋转的彩色方块,我可以调整 window 的大小并关闭 window,Visual Studio 和 Vulkan 层均出现 0 个错误。


When I change to this pattern that I've done before:当我更改为以前做过的这种模式时:

std::vector<std::shared_ptr<ImageView>> imageViews_;

and my functions become:我的功能变成:

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

It fails when It calls the create() for the ImageViews giving me an unhandled exception: access read/write violation stating that the "this" pointer within my ImageView class is nullptr .它在调用 ImageViews 的 create() 时失败,给了我一个未处理的异常:访问读/写冲突,指出我的 ImageView class 中的“this”指针是nullptr


Here is what my ImageView class looks like:这是我的 ImageView class 的样子:

ImageView.h 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 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

Within my class, I've tried having image_ as a pointer and as a non-pointer and as for the signature of create() , I've tried passing the parameters by copy, reference, pointer, const reference, const pointer, etc. and to no avail, none of the above has worked.在我的 class 中,我尝试将image_作为指针和非指针,至于create()的签名,我尝试通过复制、引用、指针、常量引用、常量指针等传递参数. 无济于事,以上都没有奏效。 Everything keeps causing an exception.一切都会导致异常。 I don't know what's causing the access violation.我不知道是什么导致了访问冲突。 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 other Vulkan Objects and did not have this issue until now. 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 对象,直到现在都没有这个问题。

What are the takes on the usages and proper setup of VkImageView and VkImage within the context of the SwapChain?在 SwapChain 的上下文中,VkImageView 和 VkImage 的用法和正确设置是什么? Currently, the VkImage s are still stored within the SwapChain as std::vector<VkImage> I can create it successfully within the class directly, but when I try to extract the VkImageView out into its own class object is when I start to run into this problem.目前, VkImage仍然作为std::vector<VkImage>存储在 SwapChain 中,我可以直接在 class 中成功创建它,但是当我尝试将 VkImageView 提取到它自己的 class ZA8CFDE68 开始运行到运行时这个问题。 I'm learning Vulkan through this tutorial and I'm starting to get a grasp of how it is designed, but I'm still no expert at the API.我正在通过本教程学习 Vulkan,并且开始了解它的设计方式,但我仍然不是 API 方面的专家。 Right now any help would be appreciated.现在任何帮助将不胜感激。 And, yes I've stepped through the debugger, I've watched my variables, I've watched the call stack, and for the life of me, I'm completely stumped.而且,是的,我已经通过调试器,我已经观察了我的变量,我已经观察了调用堆栈,而对于我的生活,我完全被难住了。 If you need more information than this please don't hesitate to ask.如果您需要更多信息,请不要犹豫。

User nicol-bolas pointed out in the comment section that I had i = std::shared_ptr<ImageView>() and that I should have had i = std::make_shared<ImageView>() and yes that is correct and that is how my other independent classes are being created.用户nicol-bolas在评论部分指出我有i = std::shared_ptr<ImageView>()并且我应该有i = std::make_shared<ImageView>()是的,这是正确的,这就是我的其他独立课程正在创建中。 This was an overlooked typo mistake.这是一个被忽视的拼写错误。 So I give credit to NicolBolas for that.因此,我将这一点归功于NicolBolas However, after fixing that bug, it allowed me to find and fix the real bug.但是,在修复了那个错误之后,它让我能够找到并修复真正的错误。

The actual bug that was causing the Unhandled Exception had nothing to do with the ImageView , VkImageView , VkImage objects.导致Unhandled Exception的实际错误与ImageViewVkImageViewVkImage对象无关。 The real culprit was within the ImageView class itself within its initialize() method.真正的罪魁祸首是ImageView class 本身在其initialize()方法中。 I was assigning its member device_ within the scope of the if statement, where I was checking to see if the device pointer being passed in was nullptr or not.我在 if 语句的device_中分配了它的成员 device_,我正在检查传入的device指针是否为nullptr

I originally had this:我最初有这个:

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

And the device_ was never being set.而且device_从未被设置。 It should have been:它应该是:

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

Now the code works again and I have a spinning colored square.现在代码再次工作,我有一个旋转的彩色方块。 The code exits with 0 errors and no messages from Vulkan Layers.代码以 0 个错误退出,并且没有来自 Vulkan 层的消息。

I had simply overlooked the {} within the if statement of the function.我只是忽略了 function 的 if 语句中的{}

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

相关问题 处理 C++ 中 vulkan 的设备、表面和交换链中 object 生命周期的第 22 个问题? - Dealing with the catch 22 of object lifetimes in vulkan's device, surface, and swapchain in C++? Oculus Rift / Vulkan:使用计算着色器写入交换链 - Oculus Rift / Vulkan : Write to swapchain with a compute shader Vulkan:调整窗口大小后重新创建交换链时出现图像错误 - Vulkan: Image error when recreating the swapchain after a window resize Vulkan 交换链对 window 系统默认帧缓冲区的作用 - What Vulkan swapchain does to the window system default framebuffer 如果没有VK_KHR_swapchain扩展名,如何运行Vulkan API? - How do I run the Vulkan API if I have no VK_KHR_swapchain extension? C++ Vulkan 交换链 image_index 与 current_frame - C++ Vulkan swapchain image_index vs current_frame Vulkan:转储当前分配的对象? - Vulkan: dump currently allocated objects? 如何正确清洁 Vulkan 对象? - How to properly clean Vulkan objects? Vulkan 验证错误表明我的图像布局错误,但只有两次我第一次呈现来自交换链的图像 - Vulkan validation errors states my images are in the wrong layout, but only the two first times I present images from the swapchain DirectX10交换链和设备指向0x00000000(导致运行时错误)(C ++) - DirectX10 swapchain and device point to 0x00000000 (causing runtime error) (c++)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM