1. 程式人生 > >Vulkan Cookbook 第五章 2 建立取樣影象

Vulkan Cookbook 第五章 2 建立取樣影象

建立取樣影象

譯者注:示例程式碼點選此處

取樣影象用於從著色器內的影象(紋理)讀取資料。通常它們與取樣器一起使用。並且為了能夠將影象用作取樣影象,必須使用VK_IMAGE_USAGE_SAMPLED_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_SAMPLED_IMAGE_BIT位確保所選影象格式適合取樣影象。
6.如果樣本影象將被線性濾波或者其mipmap將被線性濾波,通過檢查檢查是否設定了format_properties變數的optimalTilingFeatures成員的VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT確保所選格式適合於線性濾波的取樣影象。
7.獲取使用physical_device變數建立的邏輯裝置的控制代碼,並存儲在名為logical_device的VkDevice型別變數中。
8.使用logical_device和format變數建立影象,然後選擇其餘的影象引數。不要忘記在影象建立期間提供VK_IMAGE_USAGE_SAMPLED_BIT用法。將影象的控制代碼儲存在名為sampled_image的VkImage型別變數中(請參閱第四章資源和記憶體的

建立影象內容)。
9.使用VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT屬性分配記憶體物件(或使用現有的記憶體物件)並將其繫結到建立的影象(參見第四章資源和記憶體的分配記憶體物件和將其繫結到影象內容)。
10.使用logical_device、sampled_image和format變數建立影象檢視,然後選擇其餘的檢視引數。將影象檢視的控制代碼儲存在名為sampled_image_view的VkImageView型別變數中(參見第四章資源和記憶體的建立影象檢視內容)。

這個怎麼運作...

取樣影象用作著色器內的影象資料(紋理)的來源。要從影象中獲取資料,通常我們需要一個取樣器物件,它定義瞭如何讀取資料(情參閱

建立取樣器內容)。

提示:取樣影象使用VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE描述符型別。

在著色器中,我們可以使用多個取樣器以不同的方式從同一影象中讀取資料。也可以用相同的取樣器對多個影象進行取樣。但是在某些平臺上,使用組合影象取樣器物件可能更合適。該組合影象取樣器將取樣器和取樣影象聚集在一個物件中。

 並非所有影象格式都支援取樣影象,這取決於執行應用程式的平臺。但是有一組強制格式可以始終用於取樣影象和線性濾波的取樣影象。這種格式的示例包括(但不限於)下列:
·VK_FORMAT_B4G4R4A4_UNORM_PACK16
·VK_FORMAT_R5G6B5_UNORM_PACK16
·VK_FORMAT_A1R5G5B5_UNORM_PACK16
·VK_FORMAT_R8_UNORM and VK_FORMAT_R8_SNORM
·VK_FORMAT_R8G8_UNORM and VK_FORMAT_R8G8_SNORM
·VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_R8G8B8A8_SNORM, and VK_FORMAT_R8G8B8A8_SRGB ·VK_FORMAT_B8G8R8A8_UNORM and VK_FORMAT_B8G8R8A8_SRGB
·VK_FORMAT_A8B8G8R8_UNORM_PACK32, VK_FORMAT_A8B8G8R8_SNORM_PACK32, and ·VK_FORMAT_A8B8G8R8_SRGB_PACK32
·VK_FORMAT_A2B10G10R10_UNORM_PACK32
·VK_FORMAT_R16_SFLOAT
·VK_FORMAT_R16G16_SFLOAT
·VK_FORMAT_R16G16B16A16_SFLOAT
·VK_FORMAT_B10G11R11_UFLOAT_PACK32
·VK_FORMAT_E5B9G9R9_UFLOAT_PACK32

如果我們想使用一些不太典型的格式,需要檢查他是否可用於取樣影象。可以這樣完成:

VkFormatProperties format_properties;
vkGetPhysicalDeviceFormatProperties( physical_device, format, &format_properties );
if( !(format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) ) {
  std::cout << "Provided format is not supported for a sampled image." << std::endl;
  return false; 
}
if( linear_filtering &&
!(format_properties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) ) {
  std::cout << "Provided format is not supported for a linear image filtering." << std::endl;
  return false; 
}
                

如果我們確定所選的格式可用,可以建立影象、用於它的記憶體物件和影象檢視(在Vulkan中,大多數情況下影象是用影象視圖表示的)。我們需要在影象建立期間指定VK_IMAGE_USAGE_SAMPLED_BIT的使用方式:

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

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

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

當我們想要將影象用作取樣影象時,在從其載入資料到著色器內之前,需要將影象的格式轉換為VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL。

提示:為了建立表示著色器中的取樣影象的uniform變數。我們需要使用適當的關鍵字(可能具有字首)與適當的紋理維度。

可以生成SPIR-V程式集的GLSL程式碼示例(使用取樣影象)可能如下所示:

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