Resource Views

Resource Views

Buffers 和 images 是vulkan支持的两种主要的资源类型。除了创建这两种资源外,你还可对现有资源创建对应的资源视图 ,以便对其进行分区,重译内容,或者其他用途。Buffer资源的视图表示一个buffer的子范围,image的试图则可以别名格式或者访问图像的子范围。

Buffer Views

一个buffer view用来用某一特定格式重新解释buffer中的数据。假如buffer中的数据被当作一连串的纹素数据处理,那么这也称为texel buffer view。一个texel buffer view可以让shader直接访问数据,并且vulkan会自动将buffer中的纹素数据转换成shader期望的格式。一个例子为,顶点着色器可以通过读取texel buffer获取顶点属性,而不是通过vertex buffer。虽然这存在限制,但它确实允许随机访问buffer中的数据。

在结构VkBufferViewCreateInfo中,buffer vew相关的父buffer对象由字段VkBuffer指定,它所指定的buffer的子范围通过offset和range指定。注意,一个texel buffer中能存储的texel数量是有限制的,由VkPhsyicalDeviceLimits中的maxTexelBufferElements指定,所以buffer view中range除以format的结果必须小于等于限制,不过该限制保证至少大于等于65536。

当buffer view绑定一个texel buffer时,buffer中的数据被解释为指定的format字段。

Image Views

在许多情况下,image 资源不能直接使用。是因为我们在使用image 资源时往往需要比image自身更多的信息。比如,你不能直接把image当作某个buffer的附件使用,或者将image绑定到某个描述集上用来给shader采样。为了满足这些需求,你必须创建一个image view对象,包含一系列属性并且关联到某个image资源上。

image view允许将当前image的一部分或全部都当作另一个格式处理。最终格式必须和资源本身拥有相同的维度,即使image view包含资源的一部分layer或mip level。图像和视图的格式必须是兼容的,这一般代表着他们每个像素的位数相等,即便他们的格式完全不同或者图像的通道数不同。

在结构体VkImageViewCreateInfo中,引用的图像由image指定,视图的格式也由viewType指定。viewType必须和图像格式建通并且隶属于VkImageViewType中的一个。

  • VK_IMAGE_VIEW_TYPE_{1,2,3}D:正常的1D,2D,3D图像。
  • VK_IMAGE_VIEW_TYPE_CUBE{_ARRAY}:cube map和cube map array图像。
  • VK_IMAGE_VIEW_TYPE_{1,2}D_ARRAY:1D,2D array 图像。

注意所有的图像都必须考虑array图像,即使他们只有一个layer。所以,给图像中的某一个layer创建非array视图是可能的。

新试图的格式由format指定,该格式必须与图像格式兼容。一般来说,如果两个格式的像素含有同样位数,他们就被认为是兼容的。如果其中一个格式或两个格式都是压缩图像格式,那么以下一项或两个必须成立:

  • 如果两个图像都是压缩格式,那么格式下每个block含有的位数必须相同。
  • 如果其中一个格式为压缩格式,那么压缩格式block含有的位数需要和未压缩格式一个纹素含有的位数相同。

通过给一个压缩图像创建一个未压缩视图,允许访问原始压缩数据,那么从shader中向图像写入压缩数据或者让程序重新翻译压缩数据是可行的。请注意,虽然所有块压缩格式的块大小都是64位或128位,但是不存在单通道64位或128位的未压缩图像格式。要将给压缩图像格式别名为未压缩的单通道格式,你需要选择一种每texel具有相同位数的非压缩格式,然后在着色器中把通道合并,从压缩数据中提取单个字段。

视图中RGBA通道可重排。该操作是通过指定VkComponentMapping实现的。

该结构体内的每一个成员都指出图像中的源数据通道会填充到哪一个视图的通道。每个成员都是VkCommponentSwizzle枚举,包括:

  • VK_COMPONENT_SWIZZLE_{R,G,B,A}:指出原数据从图像中的哪一通道读取。
  • VK_COMPONENT_SWIZZLE_{ZERO,ONE}:忽略图像数据,当作0或1处理。
  • VK_COMPONENT_SWIZZLE_IDENTITY:从图像对应通道读取。默认值为0。

视图可以是图像的一部分。子范围通过VkImageSubresourceRange指定。

该结构体的aspectMask字段是由VkImageAspectFlagBits组成的,指出图像的那一部分收到影响。有些image类型拥有诸多逻辑部分(logical part),即便数据本身都有可能是交错的或其他相关。比如说depth-stencil image,他拥有深度信息和模板信息。这两部分都可以作为一个独立的图像看待,这些子图像就被称为aspects。aspectMask可以是:

  • VK_IMAGE_ASPECT_COLOR_BIT:图像的颜色部分。只有color image含有color aspect。
  • VK_IMAGE_ASPECT_DEPTH_BIT:depth-stencil image的depth aspect。
  • VK_IMAGE_ASPECT_STENCIL_BIT:同样的stencil 部分。
  • VK_IMAGE_ASPECT_METADATA_BIT:任何与图像相关的附加信息,用来追踪其状态。例如,用于各种压缩技术。

当你给一个image 创建了一个视图,那么它只能对某一个aspect可视。这方面给最大的例子可能就是为depth-stencil创建depth视图或stencil视图。

如果想为图像的mip chain中一个子集创建image view,指定VkImageSubresourceRange中的baseMipLevel和levelCount指定子集的mip chain从那一层为开始并且含有多少mip level。如果图像不存在mipmaps,这些字段应该设置为0或1。

同样,如果为图像array layers创建子集的image view,指定baseArrayLayer和layerCount。如果图像不是array image,baseArrayLayer设置为0,layerCount设置为1。

Image Arrays

图像类型(VkImageType)只包含VK_IMAGE_TYPE_{1,2,3}D,用来创建1D,2D,3D图像。然而,除了图像在各自x,y,z维度上的大小,所有图像都有一个用VkImageCreateInfo中arrayLayers指出的layer count。

图像可以聚合成数组,数组中的每个元素称为层。array images允许将诸多图像组成单个物体,并且相比从分散的图像中采样,在array image中多多个层进行采样拥有更好的性能表现。因为所有vulkan image都有一个laycount字段,技术上来讲,所有图像都是array image。但是实际上,我们只把laycount大于1的图像当作array image。

当我们给image创建视图时,可以显式的指出视图时array的还是nonarray的。一个nonarray视图代表该视图只含有一层,而array视图可能包含多层。从nonarray视图中采样要比只含有一层的array视图表现更好,因为设备需要执行减少的间接操作和参数查询。

1D的array纹理概念上有别于2D纹理,同样2D的array纹理也有别于3D纹理。最主要的区别在于,在2D的Y轴上采样和3D的Z轴上有线性过滤操作,但是array纹理则不存在任何过滤操作。注意到VkImageVieWType不存在3D的array image view,并大部分vulkan 实现不允许创建3D的array image。

除了image arrays,cube map是一类特殊的image类型,它允许将图像的六层当成一组,解释为立方体的六个面。想象以下你站在一个立方体房间的中心,房间有四面墙,一个地板和一个天花板。你的左边和右边是X轴的负方向和正方向,后面和前面是Z轴的负方向和正方向,下面和上面是Y轴的负方向和正方向。这六个面用\(-X,+X,-Y,+Y,-Z,+Z\) 表示。这就是cube map的六个面,一组连续的array layers就按照这个顺序解释。

cube map使用3D坐标进行采样。该坐标解释为从立方体中心为起点,向外指的一个向量。采样点就是该向量与立方体相遇的点。

为了创建一个cubemap view,首先创建一个2D array image并且至少含有六层。图像的flags字段必须设置为VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT并且image必须是正方形。

接下来我们创建image view,不过我们创建的是一个cubemap view。设置viewType为VK_IMAGE_VIEW_TPYE_CUBE。在subresourceRange中,将baseArrayLayer和layerCount设置为0和6。当然你可以通过设置其他数值来创建几个面的view。

cubemap array image则是每个六个层为一组,组成一个cubemap。创建cubemap array image,将viewType设置为VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,layercount需要是6的倍数。

posted @ 2022-08-12 15:28  ᴮᴱˢᵀ  阅读(186)  评论(0)    收藏  举报