天天看点

Vulkan Specification(Vulkan规范):第十一章 11.6. 资源内存关联

11.6. 资源内存关联

资源初始都是以_虚拟分配_ 的方式创建的,并不占内存。 设备内存被单独分配(参看设备内存),然后再和资源关联上。 这个关联操作对于稀疏、非稀疏资源来说是不同的。

任何以稀疏标志创建资源都被认为是稀疏资源。 以这些标志之外的标志创建的资源被认为是非稀疏资源。 关于稀疏资源的内存关联在 稀疏资源中有描述。

在资源被当作参数传递到以下任何一个操作之前,非稀疏资源必须完全并连续的绑定到一个

VkDeviceMemory

 对象:

  • 创建图像或者缓冲区视图
  • 更新描述符集合
  • 在命令缓冲区中记录命令

一旦绑定了,内存绑定在资源的生命周期内就是不变的。

想要知道一个缓冲区资源的内存限制条件,可调用:

void vkGetBufferMemoryRequirements(
    VkDevice                                    device,
    VkBuffer                                    buffer,
    VkMemoryRequirements*                       pMemoryRequirements);
           
  • device

     是持有缓冲区的逻辑设备。
  • buffer

     被查询的缓冲区。
  • pMemoryRequirements

     指向一个 

    VkMemoryRequirements

    实例,装载了被返回的内存限制条件信息。

Valid Usage (Implicit)

  • device

     must be a valid 

    VkDevice

     handle
  • buffer

     must be a valid 

    VkBuffer

     handle
  • pMemoryRequirements

     must be a pointer to a 

    VkMemoryRequirements

     structure
  • buffer

     must have been created, allocated, or retrieved from 

    device

想要知道图像资源内存限制条件,可调用:

void vkGetImageMemoryRequirements(
    VkDevice                                    device,
    VkImage                                     image,
    VkMemoryRequirements*                       pMemoryRequirements);
           
  • device

     是拥有该图像的逻辑设备。
  • image

     是被查询的图像。
  • pMemoryRequirements

     指向了一个

    VkMemoryRequirements

    是列,装载了该图像对象内存限制条件信息。

Valid Usage (Implicit)

  • device

     must be a valid 

    VkDevice

     handle
  • image

     must be a valid 

    VkImage

     handle
  • pMemoryRequirements

     must be a pointer to a 

    VkMemoryRequirements

     structure
  • image

     must have been created, allocated, or retrieved from 

    device

VkMemoryRequirements

类型数据结构定义如下:

typedef struct VkMemoryRequirements {
    VkDeviceSize    size;
    VkDeviceSize    alignment;
    uint32_t        memoryTypeBits;
} VkMemoryRequirements;
           
  • size

     该资源所需的内存分配的大小,以字节为单位。
  • alignment

     是资源所要求的内存分配的对齐大小,以字节为单位。
  • memoryTypeBits

     是一个标志位,每一bit表示每一个受支持的内存类型。但是, 只有当 

    i

     在物理设备支持的内存类型 

    VkPhysicalDeviceMemoryProperties

    中的时候,

    i

     才会被设置。

Vulkan实现保证关于内存限制条件的某些属性通过

vkGetBufferMemoryRequirements

 和

vkGetImageMemoryRequirements

返回:

  • memoryTypeBits

     成员总是至少包含一个被设置的bit位。
  • buffer

     是一个在创建时没有带有 

    VK_BUFFER_CREATE_SPARSE_BINDING_BIT

     的

    VkBuffer

    ,或者若

    image

    是在创建时 

    VkImageCreateInfo

    tiling

     成员带有 

    VK_IMAGE_TILING_LINEAR

     的

    VkImage

    ,那么此

    memoryTypeBits

    成员总是至少包含一个被设置的bit位,对应一个带有

    propertyFlags

    的 

    VkMemoryType

    ,该

    propertyFlags

    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT

     bit 和 

    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT

     bit 都被设置。 换言之,可映射的一致性内存可以总是被附着到这些对象上。
  • memoryTypeBits

     成员总是至少包含一个被设置的bit位,对应着带有一个

    propertyFlags

    VkMemoryType

     , 该

    propertyFlags

     的

    VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT

     bit 被设置。
  • memoryTypeBits

     成员和所有的 创建时传递给

    vkCreateBuffer

    的 

    VkBufferCreateInfo

    中 带有相同 

    flags

     and 

    usage

    VkBuffer

     对象相同, Further, if 

    usage1

     and 

    usage2

     of type 

    VkBufferUsageFlags

     are such that the bits set in 

    usage2

     are a subset of the bits set in 

    usage1

    , and they have the same 

    flags

    , then the bits set in

    memoryTypeBits

     returned for 

    usage1

     必须 be a subset of the bits set in 

    memoryTypeBits

     returned for 

    usage2

    , for all values of 

    flags

    .
  • alignment

     成员值是2的幂。
  • alignment

     成员与 传递给name:vkCreateBuffer的

    VkBufferCreateInfo

    数据结构的成员

    usage

     和 

    flags

     的相同bit组合 而创建的所有 

    VkBuffer

     对象 相同。
  • 对于被创建时带有一个颜色格式的图像, 

    memoryTypeBits

     成员与 创建时传递给

    vkCreateImage

    VkImageCreateInfo

     数据结构中的

    tiling

    成员, 

    flags

    成员的

    VK_IMAGE_CREATE_SPARSE_BINDING_BIT

     bit和 name:usage成员的 

    VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT

     的组合相同 所有的

    VkImage

     对象完全一致。
  • 对于被创建时带有一个depth/stencil 格式的图像, 

    memoryTypeBits

     成员与 创建时传递给 

    vkCreateImage

    函数的

    VkImageCreateInfo

    数据结构的 

    format

     成员、

    tiling

    成员,  

    flags

     成员的

    VK_IMAGE_CREATE_SPARSE_BINDING_BIT

     bit、

    usage

     成员的

    VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT

     的组合值相同的 所有 

    VkImage

     对象。
  • 若内存要求是为

    VkImage

    准备的,

    memoryTypeBits

     成员必须不能指代一个 

    propertyFlags

    VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT

     bit 被设置的

    VkMemoryType

    ,若传递给

    vkCreateImage

    的数据结构的 

    VkImageCreateInfo

    的 

    vkGetImageMemoryRequirements

    ::

    image

    的成员

    usage

    VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT

     bit 没有被设置。
  • 若内存要求是为

    VkBuffer

    准备的, 

    memoryTypeBits

     成员必须不能指代一个

    propertyFlags

    VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT

     bit被设置的 

    VkMemoryType

    注意

    此要求的隐藏含义是 该惰性分配的内存不适用于所有情形的缓冲区。

把内存附着在一个缓冲区对象,可调用:

VkResult vkBindBufferMemory(
    VkDevice                                    device,
    VkBuffer                                    buffer,
    VkDeviceMemory                              memory,
    VkDeviceSize                                memoryOffset);
           
  • device

     是拥有该缓冲区和内存的逻辑设备。
  • buffer

     是缓冲区。
  • memory

     是一个 

    VkDeviceMemory

     类型对象,描述了需附着的设备内存。
  • memoryOffset

     是  

    memory

    区域的起始偏移,该内存被绑定到缓冲区上。 被返回的

    memory

    的成员

    VkMemoryRequirements

    ::

    size

     带有的字节数,从

    memoryOffset

     开始的字节数, 将被绑定到特定的缓冲区。

Valid Usage

  • buffer

     本身不能是内存对象。
  • buffer

     被创建时不能带有稀疏内存绑定标识位。
  • memoryOffset

     必须小于

    memory

    的大小。
  • 若创建

    buffer

     时带有 

    VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT

    VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT

    memoryOffset

     必须是

    VkPhysicalDeviceLimits

    ::

    minTexelBufferOffsetAlignment

    的倍数。
  • 若创建

    buffer

     时带有 

    VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT

    memoryOffset

     必须是

    VkPhysicalDeviceLimits

    ::

    minUniformBufferOffsetAlignment

    的倍数。
  • 若创建

    buffer

     时带有 

    VK_BUFFER_USAGE_STORAGE_BUFFER_BIT

    memoryOffset

     必须是

    VkPhysicalDeviceLimits

    ::

    minStorageBufferOffsetAlignment

    的倍数。
  • memory

     被分配时必须使用 以

    buffer

    为参数调用

    vkGetBufferMemoryRequirements

    而返回的 

    VkMemoryRequirements

     数据结构的

    memoryTypeBits

    成员中被允许的内存类型。
  • memoryOffset

     必须是一个 以 

    buffer

    为参数调用 

    vkGetBufferMemoryRequirements

     而返回的 

    VkMemoryRequirements

     数据结构

    alignment

    成员 的倍数的正整数。
  • buffer

    为参数调用

    vkGetBufferMemoryRequirements

     而返回的 

    VkMemoryRequirements

     数据结构的

    size

     成员 必须 小于或 等于 

    memory

    减去 

    memoryOffset

    之差。

Valid Usage (Implicit)

  • device

     must be a valid 

    VkDevice

     handle
  • buffer

     must be a valid 

    VkBuffer

     handle
  • memory

     must be a valid 

    VkDeviceMemory

     handle
  • buffer

     must have been created, allocated, or retrieved from 

    device

  • memory

     must have been created, allocated, or retrieved from 

    device

Host Synchronization

  • Host access to 

    buffer

     must be externally synchronized

Return Codes

Success

  • VK_SUCCESS

Failure

  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

把内存附着到一个图像对象上,可调用:

VkResult vkBindImageMemory(
    VkDevice                                    device,
    VkImage                                     image,
    VkDeviceMemory                              memory,
    VkDeviceSize                                memoryOffset);
           
  • device

     是拥有该图像和内存的逻辑设备。
  • image

     是图像。
  • memory

     是一个

    VkDeviceMemory

    对象,描述了需被附着的设备内存。
  • memoryOffset

     绑定到该图像的内存的区域的起始偏移。 

    memory

    VkMemoryRequirements

    ::

    size

     成员里被返回的字节数量,从

    memoryOffset

     字节开始, 将被绑定到特定的图像。

Valid Usage

  • image

     实际内存不能是内存对象。
  • image

     被创建是不能带有稀疏内存绑定flags。
  • memoryOffset

     必须小于 

    memory

    的大小。
  • memory

     必须在创建时使用 以 

    image

    为参数调用 

    vkGetImageMemoryRequirements

     而返回的 

    VkMemoryRequirements

    数据结构的

    memoryTypeBits

    成员中被允许的内存类型之一。
  • memoryOffset

     必须是 以 

    image

    为参数调用 

    vkGetImageMemoryRequirements

     而返回的 

    VkMemoryRequirements

    数据结构的 

    alignment

    成员的正整数倍。
  • image

    为参数调用

    vkGetImageMemoryRequirements

     而返回的 

    VkMemoryRequirements

    数据结构的

    size

     成员 必须 小于或 等于  

    memory

     减去 

    memoryOffset

    之差。

Valid Usage (Implicit)

  • device

     must be a valid 

    VkDevice

     handle
  • image

     must be a valid 

    VkImage

     handle
  • memory

     must be a valid 

    VkDeviceMemory

     handle
  • image

     must have been created, allocated, or retrieved from 

    device

  • memory

     must have been created, allocated, or retrieved from 

    device

Host Synchronization

  • Host access to 

    image

     must be externally synchronized

Return Codes

Success

  • VK_SUCCESS

Failure

  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

Buffer-Image Granularity

There is an implementation-dependent limit, 

bufferImageGranularity

, which specifies a page-like granularity at which buffer, linear image and optimal image resources 必须 be placed in adjacent memory locations to avoid aliasing. Two resources which do not satisfy this granularity requirement are said to alias. Linear image resource are images created with 

VK_IMAGE_TILING_LINEAR

 and optimal image resources are those created with

VK_IMAGE_TILING_OPTIMAL

bufferImageGranularity

 is specified in bytes, and 必须 be a power of two. Implementations which do not require such an additional granularity may report a value of one.

注意

bufferImageGranularity

 is really a granularity between "linear" resources, including buffers and images with linear tiling, vs. "optimal" resources, i.e. images with optimal tiling. It would have been better named "linearOptimalGranularity".

Given resourceA at the lower memory offset and resourceB at the higher memory offset in the same 

VkDeviceMemory

 object, where one of the resources is a buffer或 a linear image and the other is an optimal image, and the following:

resourceA.end       = resourceA.memoryOffset + resourceA.size - 1
resourceA.endPage   = resourceA.end & ~(bufferImageGranularity-1)
resourceB.start     = resourceB.memoryOffset
resourceB.startPage = resourceB.start & ~(bufferImageGranularity-1)
           

The following property 必须 hold:

resourceA.endPage < resourceB.startPage
           

That is, the end of the first resource (A) and the beginning of the second resource (B) 必须 be on separate “pages” of size 

bufferImageGranularity

bufferImageGranularity

 may be different than the physical page size of the memory heap. This restriction is only needed when a buffer或 a linear image is at adjacent memory location with an optimal image and both will被用于 simultaneously. Adjacent buffers’或 adjacent images' memory ranges可以 be closer than 

bufferImageGranularity

, provided they meet the 

alignment

 requirement for the objects in question.

Sparse block size in bytes and sparse image and buffer memory alignments 必须 all be multiples of the 

bufferImageGranularity

. Therefore, memory bound to sparse resources naturally satisfies the

bufferImageGranularity

.