Vulkan Cookbook 第四章 11 映射、更新和取消映射主机可见内存

映射、更新和取消映射主机可见内存

译者注:示例代码点击此处

对于渲染期间使用的图像和缓冲区,建议绑定位于图像硬件(设备本地内存)上的内存。这会产生最好的表现。但我们不能直接访问这样的内存,需要使用中间(暂存)资源来调节GPU(设备)和CPU(主机)之间的数据传输。

另一方面,暂存资源需要使用主机可见的内存。要将数据上传到此类内存或从中读取数据,我们需要对其进行映射。

怎么做...

1.获取已创建的逻辑设备句柄并将其存储在名为logical_device的VkDevice类型变量中。
2.选择在具有VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT属性的内存类型上分配的内存对象。将内存对象的句柄储存在名为memory_object的VkDeviceMemory类型变量中。
3.选择应映射和更新的内存区域。将内存对象的内存开头的偏移量(以字节为单位)存储在名为offset的VkDeviceSize类型变量中。
4.选择要复制到内存对象的选定区域的数据大小。使用名为data_size的VkDeviceSize类型变量表示数据大小。
5.准备应该复制到内存对象的数据。并使用它来初始名为data的void*类型的变量。
6.创建一个名为pointer的void *类型型变量。它将包含指向映射内存范围的指针。
7.调用vkMapMemory( logical_device, memory_object, offset, data_size, 0, &local_pointer )进行内存映射,提供逻辑设备句柄和内存对象的句柄,偏离内存的起始点和我们想要映射的区域的大小(以字节为单位),0值和指向local_pointer变量的指针。
8.检查返回的值是否等于VK_SUCCESS来确保调用成功。
9.将准备好的数据复制到指针变量指向的内存中。它可以通过以下调用完成:std::memcpy( local_pointer, data, data_size )。
10.创建一个名为memory_ranges的std::vector<VkMappedMemoryRange>类型变量。向每个元素初始化一下值:
    ·sType为VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE
    ·pNext为nullptr
    ·memory为memory_object
    ·offset为每个范围的偏移量
    ·size为每个范围的尺寸
11.通知驱动程序内存的哪些部分已更改。通过调用vkFlushMappedMemoryRanges( logical_device, static_cast<uint32_t>(memory_ranges.size()), &memory_ranges[0] )来完成此操作,为其提供logical_device变量、要更改内存的范围数量(memory_ranges向量中的元素数量)和指向memory_ranges向量的第一个元素的指针。
12.确保调用返回VK_SUCCESS值刷新成功。
13.要取消映射内存,请调用vkUnmapMemory( logical_device, memory_object )。

这个怎么运作...

映射内存是将数据上载到Vulkan资源的最简单方法。在映射期间我们指定应该映射哪个内存部分(从内存对象的开头偏移和映射范围的大小):

VkResult result;
void * local_pointer;
result = vkMapMemory( logical_device, memory_object, offset, data_size, 0, &local_pointer ); 
if( VK_SUCCESS != result ) {
  std::cout << "Could not map memory object." << std::endl;
  return false; 
}

映射为我们提供了指向所请求的内存部分的指针。我们可以使用这个指针,就像在典型的C++应用程序中使用的其他指针一样。是否从这样的内存写入或读取数据没有限制。下面将数据从应用程序赋值到内存对象:

std::memcpy( local_pointer, data, data_size );

当我们更新映射的内存范围时,需要通知驱动程序内存内容已被修改,上传的数据可能不会立即对提交给队列的其他操作可见。通知CPU(主机)执行的内存数据修改称为刷新。为此我们准备了一个更新的内存范围列表,不需要覆盖整个映射内存:


std::vector<VkMappedMemoryRange> memory_ranges = { 
  {
  VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 
  nullptr,
  memory_object,
  offset,
  data_size
  } 
};

vkFlushMappedMemoryRanges( logical_device, static_cast<uint32_t>(memory_ranges.size()), &memory_ranges[0] ); 
if( VK_SUCCESS != result ) {
  std::cout << "Could not flush mapped memory." << std::endl;
  return false; 
}

当我们完成处理映射内存之后,可以取消映射它。内存映射不应该影响我们应用程序的性能,可以在我们的应用程序的整个生命周期中保留获取的指针。但是我们应该在关闭应用程序并销毁所有资源之释放它(unmap):

if( unmap ) {
  vkUnmapMemory( logical_device, memory_object );
} else if( nullptr != pointer ) { 
  *pointer = local_pointer;
}

return true;

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Computer graphics have a very long and interesting history. Many APIs or custom approaches to the generation of 2D or 3D images have come and gone. A landmark in this history was the invention of OpenGL, one of the first graphics libraries, which allowed us to create real-time, high-performance 3D graphics, and which was available for everyone on multiple operating systems. It is still developed and widely used even today. And this year we can celebrate its 25th birthday! But many things have changed since OpenGL was created. The graphics hardware industry is evolving very quickly. And recently, to accommodate these changes, a new approach to 3D graphics rendering was presented. It took the form of a low-level access to the graphics hardware. OpenGL was designed as a high-level API, which allows users to easily render images on screen. But this high-level approach, convenient for users, is difficult for graphics drivers to handle. This is one of the main reasons for restricting the hardware to show its full potential. The new approach tries to overcome these struggles–it gives users much more control over the hardware, but also many more responsibilities. This way application developers can release the full potential of the graphics hardware, because the drivers no longer block them. Low-level access allows drivers to be much smaller, much thinner. But these benefits come at the expense of much more work that needs to done by the developers. The first evangelist of the new approach to graphics rendering was a Mantle API designed by AMD. When it proved that low-level access can give considerable performance benefits, other companies started working on their own graphics libraries. One of the most notable representatives of the new trend were Metal API, designed by Apple, and DirectX 12, developed by Microsoft. But all of the above libraries were developed with specific operating systems and/or hardware in mind. There was no open and multiplatform standard such as OpenGL. Until last year. Year 2016 saw the release of the Vulkan API, developed by Khronos consortium, which maintains the OpenGL library. Vulkan also represents the new approach, a low-level access to the graphics hardware, but unlike the other libraries it is available for everyone on multiple operating systems and hardware platforms–from high-performance desktop computers with Windows or Linux operating systems, to mobile devices with Android OS. And as it is still being very new, there are few resources teaching developers how to use it. This book tries to fill this gap.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值