欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > (八)图像视图

(八)图像视图

2025/4/5 4:04:18 来源:https://blog.csdn.net/directx3d_beginner/article/details/146988074  浏览:    关键词:(八)图像视图

对于每个图像,都有个图像视图,用来说明图像如何用,以及用图像的哪一部分。
和前面类似,图像视图都有个创建信息
VkImageViewCreateInfo createInfo = {};,
创建时

	vkCreateImageView(device, &createInfo, nullptr, &swapChainImageViews[i]);

很可能不止一个图像,也就要创建不止一个图像视图,即图像视图数组

//图像视图数组
std::vector<VkImageView> swapChainImageViews;

同样销毁时也要逐个销毁

for (auto imageView : swapChainImageViews  )
{vkDestroyImageView(device, imageView, nullptr);
}

运行结果仍然是空白。

完整代码如下:
MyApplication.h
#pragma once
#include <Windows.h>
#include <glm/vec4.hpp>
#include <glm/mat4x4.hpp>
#include <vulkan/vulkan.h>
#include <vulkan/vulkan_win32.h>
#include
#include “D:/install/filament-v1.18.0/third_party/imgui/examples/libs/glfw/include/GLFW/glfw3.h”
#include
#include
#include
#include
#include

//队列族索引,同时支持绘制指令的队列族和支持表现的队列族
struct QueueFaminliyIndices
{
//-1表示没找到满足需求的队列族
int graphicsFamily = -1;
int presentFamily = -1;
bool isCompleted()
{
return graphicsFamily >= 0 && presentFamily >= 0;
}
};

//交换链细节信息
struct SwapChainSupportDetails
{
VkSurfaceCapabilitiesKHR capabilities; //基础表面特性(最大/最小图像数量,宽度,高度)
std::vector formats; //表面格式(像素格式,颜色空间)
std::vector presentModes; //可用的呈现模式
};

class MyApplication
{
public:
void run();

private:
//初始化窗口
void initWindow();
//初始化Vulkan对象
void initVulkan();
//主循环进行渲染操作
void mainLoop();
//资源清理
void cleanUp();

//创建一个实例初始化Vulkan库,指定驱动程序需要使用的应用程序信息
void createInstance();
//查询显卡设备
void pickPhysicalDevice();//返回查找的队列族索引
QueueFaminliyIndices findQueueFamilies(VkPhysicalDevice device);
//确保选择的设备能执行需要的指令
bool isDeviceSuitable(VkPhysicalDevice device);
//创建逻辑设备
void createLogicalDevice();
//创建表面
void createSurface();
//检测所需的扩展是否存在
bool checkDeviceExtensionSupport(VkPhysicalDevice device);
//查询交换链结构体
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device);
//选择合适的表面格式
VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats);
//选择呈现模式
VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR> availablePresentModes);
//设置交换范围
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities);
//创建交换链
void createSwapChain();//创建图像视图
void createImageViews();

private:
//窗口
GLFWwindow* window = nullptr;

//实例句柄
VkInstance instance;
//存储显卡信息
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
//逻辑设备
VkDevice device;
//存储逻辑设备的队列句柄
VkQueue graphicsQueue;//窗口表面
VkSurfaceKHR surface;
//呈现队列
VkQueue presentQueue;//各种设备扩展(包含交换链扩展)
const std::vector<const char*> deviceExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME
};//交换链
VkSwapchainKHR swapChain;//交换链图像句柄数组
std::vector<VkImage> swapChainImages;
//交换链图像格式
VkFormat swapChainImageFormat;
//交换链图像范围
VkExtent2D swapChainExtent;//图像视图数组
std::vector<VkImageView> swapChainImageViews;

};
MyApplication.cpp
#include “MyApplication.h”

const int WIDTH = 800;
const int HEIGHT = 600;
void MyApplication::run()
{
initWindow();
initVulkan();
mainLoop();
cleanUp();
}

void MyApplication::initWindow()
{

//初始化GLFW库,
glfwInit();
//阻止创建OpenGL上下文
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
//禁止窗口大小改变
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
//存储窗口句柄
window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan window", nullptr, nullptr);

}

void MyApplication::initVulkan()
{
createInstance();
createSurface();
pickPhysicalDevice();
createLogicalDevice();
createSwapChain();
createImageViews();
}

void MyApplication::mainLoop()
{
//在没有错误和窗口没有被关闭下一直运行,事件循环
while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
}
}

void MyApplication::cleanUp()
{
for (auto imageView : swapChainImageViews )
{
vkDestroyImageView(device, imageView, nullptr);
}
vkDestroySwapchainKHR(device, swapChain, nullptr);
vkDestroyDevice(device, nullptr);
vkDestroySurfaceKHR(instance, surface, nullptr);
vkDestroyInstance(instance, nullptr);
glfwDestroyWindow(window);
glfwTerminate();
}

void MyApplication::createInstance()
{
//应用程序信息,便于优化
VkApplicationInfo appInfo = {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = “Hello Triangle”;
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.pEngineName = “No Engine”;
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.apiVersion = VK_API_VERSION_1_0;

//创建Vulkan驱动程序需要的信息
VkInstanceCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo;//返回需要的窗口交互扩展
uint32_t glfwExtensionCount = 0;
const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
createInfo.enabledExtensionCount = glfwExtensionCount;
createInfo.ppEnabledExtensionNames = glfwExtensions;//全局扩展层(对整个应用程序都有效,而不仅仅对一个设备有效)
//暂时设置为0,不使用全局扩展层
createInfo.enabledLayerCount = 0;//创建Vulkan实例
VkResult result = vkCreateInstance(&createInfo,	//包含创建信息的结构体指针nullptr,		//自定义的分配器回调函数,暂时设置为nullptr,不使用&instance);		//指向新对象句柄存储位置的指针。//检测扩展支持
//获取扩展数量
uint32_t extensionCount = 0;
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
//存储信息数组
std::vector<VkExtensionProperties> extensions(extensionCount);vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());

}

void MyApplication::pickPhysicalDevice()
{
//获取显卡设备数量
uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);

//获取显卡数组
std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());//选择合适的
for (const auto& device : devices)
{if (isDeviceSuitable(device)){physicalDevice = device;break;}
}

}

QueueFaminliyIndices MyApplication::findQueueFamilies(VkPhysicalDevice device)
{
//获取设备的队列族个数
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
//获取队列族数组
std::vector queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());

QueueFaminliyIndices indices;
//支持
//1,图形指令
//2,呈现图像到窗口表面能力
int i = 0;
for (const auto& queueFamily : queueFamilies  )
{if (queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT){indices.graphicsFamily = i;}VkBool32 presentSupport = false;vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);if (queueFamily.queueCount > 0 && presentSupport){indices.presentFamily = i;}if (indices.isCompleted()){break;}i++;
}
return indices;

}

bool MyApplication::isDeviceSuitable(VkPhysicalDevice device)
{
QueueFaminliyIndices indices = findQueueFamilies(device);
bool extensionsSupported = checkDeviceExtensionSupport(device);
bool swapChainAdequate = false;
if (extensionsSupported)
{
SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device);
swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty();
}
return indices.isCompleted() && extensionsSupported && swapChainAdequate;
}

void MyApplication::createLogicalDevice()
{
//同时图形能力和呈现到表面能力
QueueFaminliyIndices indices = findQueueFamilies(physicalDevice);
std::set uniqueQueueFamilies = { indices.graphicsFamily, indices.presentFamily };

std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
float queuePriority = 1.0f;//遍历各个队列族,
for (int queueFamily : uniqueQueueFamilies)
{VkDeviceQueueCreateInfo queueCreateInfo = {};queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;queueCreateInfo.queueFamilyIndex = queueFamily;queueCreateInfo.queueCount = 1;queueCreateInfo.pQueuePriorities = &queuePriority;queueCreateInfos.push_back(queueCreateInfo);
}
//应用的设备特性
VkPhysicalDeviceFeatures deviceFeatures = {};//创建逻辑设备
VkDeviceCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
createInfo.pQueueCreateInfos = queueCreateInfos.data();
createInfo.queueCreateInfoCount = static_cast<uint32_t> (queueCreateInfos.size());
createInfo.pEnabledFeatures = &deviceFeatures;
//启动各种设备扩展
createInfo.enabledExtensionCount = static_cast<uint32_t> (deviceExtensions.size());
createInfo.ppEnabledExtensionNames = deviceExtensions.data();//暂时不用校验层
createInfo.enabledLayerCount = 0;
vkCreateDevice(physicalDevice, &createInfo, nullptr, &device);//获取队列族的队列句柄
vkGetDeviceQueue(device, indices.graphicsFamily, 0, &graphicsQueue);
vkGetDeviceQueue(device, indices.presentFamily, 0, &presentQueue);

}

void MyApplication::createSurface()
{
//创建窗口表面
glfwCreateWindowSurface(
instance, //vkInstance对象
window, //GLFW窗口指针
nullptr, //自定义内存分配器
&surface); //存储返回的表面的内存地址

}

bool MyApplication::checkDeviceExtensionSupport(VkPhysicalDevice device)
{
uint32_t extensionCount;
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
std::vector availableExtensions(extensionCount);
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());

std::vector<std::string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());
for (const auto& extension : availableExtensions  )
{std::string strName = extension.extensionName;requiredExtensions.erase(std::remove(requiredExtensions.begin(), requiredExtensions.end(), strName),requiredExtensions.end());
}
return requiredExtensions.empty();

}

SwapChainSupportDetails MyApplication::querySwapChainSupport(VkPhysicalDevice device)
{
SwapChainSupportDetails details;
//查询基础表面特性
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities);

//格式数量->数组
uint32_t formatCount;
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
if (formatCount != 0)
{details.formats.resize(formatCount);vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data());}
//呈现模式数量->数组
uint32_t presentModeCount;
vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);
if (presentModeCount != 0)
{details.presentModes.resize(presentModeCount);vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, details.presentModes.data());
}return details;

}

VkSurfaceFormatKHR MyApplication::chooseSwapSurfaceFormat(const std::vector& availableFormats)
{
for (const auto& availableFormat: availableFormats)
{
if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
{
return availableFormat;
}
}
return availableFormats[0];
}

VkPresentModeKHR MyApplication::chooseSwapPresentMode(const std::vector availablePresentModes)
{
for (const auto& availablePresentMode : availablePresentModes)
{
if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR)
{
return availablePresentMode;
}
}
return VK_PRESENT_MODE_FIFO_KHR;
}

VkExtent2D MyApplication::chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities)
{
if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max())
{
return capabilities.currentExtent;
}
VkExtent2D actualExtent = { WIDTH, HEIGHT };
actualExtent.width = std::max(capabilities.minImageExtent.width, std::min(capabilities.maxImageExtent.width, actualExtent.width));
actualExtent.height = std::max(capabilities.minImageExtent.height, std::min(capabilities.maxImageExtent.height, actualExtent.height));

return actualExtent;

}

void MyApplication::createSwapChain()
{
SwapChainSupportDetails swapChainSupport = querySwapChainSupport(physicalDevice);
VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats);
VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes);
VkExtent2D extent = chooseSwapExtent(swapChainSupport.capabilities);

//交换链的图像数量(最小图像数+1进行三倍缓冲)
uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;
if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount)
{imageCount = swapChainSupport.capabilities.maxImageCount;
}//交换链信息结构体
VkSwapchainCreateInfoKHR createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
createInfo.surface = surface;
createInfo.minImageCount = imageCount;
createInfo.imageFormat = surfaceFormat.format;
createInfo.imageColorSpace = surfaceFormat.colorSpace;
createInfo.imageExtent = extent;
createInfo.imageArrayLayers = 1;
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; //将图像作为一个颜色附着使用//同时图形能力和呈现到表面能力
QueueFaminliyIndices indices = findQueueFamilies(physicalDevice);
uint32_t queueFamilyIndices[] = { (uint32_t)indices.graphicsFamily, (uint32_t)indices.presentFamily };
if (indices.graphicsFamily != indices.presentFamily)
{createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; //协同模式:图像可以在多个队列族间使用,不需要显式改变图像所有权createInfo.queueFamilyIndexCount = 2;  //共享所有权的队列族数,至少2个createInfo.pQueueFamilyIndices = queueFamilyIndices;  //共享所有权的队列族索引}
else
{createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; //一张图像同一时间只能被一个队列族所拥有。性能最佳。createInfo.queueFamilyIndexCount = 0;createInfo.pQueueFamilyIndices = nullptr;
}
createInfo.preTransform = swapChainSupport.capabilities.currentTransform;	//图像的固定变化操作(旋转等)
createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;		//暂时忽略掉alpha通道
createInfo.presentMode = presentMode;	//设置呈现方式
createInfo.clipped = VK_TRUE;	//不关心被窗口系统中的其它窗口遮挡的像素颜色
createInfo.oldSwapchain = VK_NULL_HANDLE;		//创建该交换链之前的旧的交换链(这里暂时没有)//创建交换链
vkCreateSwapchainKHR(device, &createInfo, nullptr, &swapChain);//交换链图像数量->数组
vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr);
swapChainImages.resize(imageCount);
vkGetSwapchainImagesKHR(device, swapChain, &imageCount, swapChainImages.data());swapChainImageFormat = surfaceFormat.format;
swapChainExtent = extent;

}

void MyApplication::createImageViews()
{
//遍历所有交换链图像,创建图像视图
swapChainImageViews.resize(swapChainImages.size());
for (size_t i = 0; i < swapChainImages.size(); i++)
{
VkImageViewCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.image = swapChainImages[i];
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; //二维纹理
createInfo.format = swapChainImageFormat;
//默认映射
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;//创建图像视图vkCreateImageView(device, &createInfo, nullptr, &swapChainImageViews[i]);}

}
调用main.cpp
#define GLFW_INCLUDE_VULKAN
#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include “MyApplication.h”

int main()
{
MyApplication app;
app.run();
return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词