1. 程式人生 > >Vulkan Cookbook 第五章 4 建立儲存影象

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>;