Vulkan Cookbook 第五章 4 创建存储图像

创建存储图像

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

存储图像准许我们从绑定到管道的图像加载(未过滤的)数据。但更重要的是,它还准许我们在图像中存储着色器中的数据。必须使用指定的VK_IMAGE_USAGE_STORAGE_BIT标志创建此图像

怎么做...

  1. 获取物理设备句柄并将其存储在名为physical_device的VkPhysicalDevice类型变量中。
  2. 选择将用于存储图像的格式初始化名为format的VkFormat类型变量。
  3. 创建一个名为format_properties的VkFormatProperties类型变量。
  4. 调用vkGetPhysicalDeviceFormatProperties( physical_device, format, &format_properties ),并提供physical_device。format变量和指向format_properties变量的指针。
  5. 通过检查是否设置了format_properties变量的optimalTilingFeatures成员的VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT位来检查所选图像格式是否适合存储图像。
  6. 如果将对存储图像执行原子操作,请确保所选格式支持它们,通过检查是否设置了format_properties变量的optimalTilingFeatures成员的VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT位来执行此操作。
  7. 获取从physical_device创建的逻辑设备句柄,并使用它来初始化名为logical_device的VkDevice类型变量。
  8. 使用logical_device和format变量创建图像,然后选择其余的图像参数。确保在图像创建期间指定了VK_IMAGE_USAGE_STORAGE_BIT用法。将创建的句柄存储在名为storage_image的VkImage类型变量中(请参阅第四章资源和内存的创建图像内容)。
  9. 使用VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT属性分配内存对象(或使用现有内存对象的特定范围)并将其绑定到图像(请参阅第四章,资源和内存的分配内存对象和将其绑定到图像内容)。
  10. 使用logical_device、storage_image和format变量创建图像视图,然后选择其余的视图参数。将图像视图的句柄存储在名为storage_image_view的VkImageView类型变量中(请参阅第四章资源和内存的创建图像视图内容)。

这个怎么运作...

当我们想要在着色器中存储图像的数据时,需要使用存储图像。也可以从这些图像加载数据,但这些加载是为过滤的(我们不能将采样器用于存储图像)。

提示:存储图像对应于VK_DESCRIPTOR_TYPE_STORAGE_IMAGE类型的描述符。

使用VK_IMAGE_USAGE_STORAGE_BIT用法创建存储图像。我们也不能忘记指定正确的格式。并非所有格式都可以用于存储图像。这取决于我们的应用程序执行的平台。但是所有Vulkan驱动程序都一定支持强制格式列表。它包括(但不限于)以下格式:

  • VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_SNORM, VK_FORMAT_R8G8B8A8_UINT, and VK_FORMAT_R8G8B8A8_SINT
  • VK_FORMAT_R16G16B16A16_UINT, VK_FORMAT_R16G16B16A16_SINT and ·VK_FORMAT_R16G16B16A16_SFLOAT
  • VK_FORMAT_R32_UINT, VK_FORMAT_R32_SINT and VK_FORMAT_R32_SFLOAT
  • VK_FORMAT_R32G32_UINT, VK_FORMAT_R32G32_SINT and VK_FORMAT_R32G32_SFLOAT
  • VK_FORMAT_R32G32B32A32_UINT, VK_FORMAT_R32G32B32A32_SINT and VK_FORMAT_R32G32B32A32_SFLOAT

如果我们想对存储图像执行原子操作,则强制格式列表要短得多:

  • VK_FORMAT_R32_UINT
  • VK_FORMAT_R32_SINT 

如果存储图像需要其他格式,或者如果我们需要使用其他格式对存储图像执行原子操作,则必须检查执行应用程序的平台是否支持所选格式。这可以使用以下代码完成:

VkFormatProperties format_properties; 
vkGetPhysicalDeviceFormatProperties( physical_device, format, &format_properties ); 
if( !(format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) ) { 
  std::cout << "Provided format is not supported for a storage image." << std::endl; 
  return false; 
} 
if( atomic_operations && 
    !(format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT) )
 { 
  std::cout << "Provided format is not supported for atomic operations on storage images." << std::endl; 
  return false; 
}

如果支持该格式,我们照常创建图像,但是需要指定VK_IMAGE_USAGE_STORAGE_BIT用法。图像准备好后,需要创建一个内存对象,将其绑定到图像,我们还需要一个图像视图可以像这样:

if( !CreateImage( logical_device, type, format, size, num_mipmaps, num_layers, VK_SAMPLE_COUNT_1_BIT, usage | VK_IMAGE_USAGE_STORAGE_BIT, false, storage_image ) ) {
  return false;
}

if( !AllocateAndBindMemoryObjectToImage( physical_device, logical_device, storage_image, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, memory_object ) ) {
  return false;
}

if( !CreateImageView( logical_device, storage_image, view_type, format, aspect, storage_image_view ) ) {
  return false;
}
return true;

在可以从着色器加载或存储到存储图像的数据之前,必须执行到VK_IMAGE_LAYOUT_GENERA布局的转换。它是支持这些操作的唯一布局。

提示:在GLSL着色器内部,存储图像使用image关键字(可能带有前缀)和适当的维度来指定。我们需要在layout限定符中提供图像的格式。

GLSL着色器中存储图像的定义示例如下:

layout (set=m, binding=n, r32f) uniform image2D <variable name>;

猜你喜欢

转载自blog.csdn.net/qq_19473837/article/details/85225504