I am struggling to understand a simple feature I need to query using the Vulkan API: I need to determine all the texture formats supported by my GPU. After searching around, I found this code:
uint32_t formatCount;
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
if (formatCount != 0) {
details.formats.resize(formatCount);
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data());
int counter = 0;
int numFormats = details.formats.size();
for (const auto& format : details.formats) {
VkFormat vkFormat = format.format;
VkColorSpaceKHR colorSpace = format.colorSpace;
std::cout << "[" << counter << "] Format: " <<
vkFormatToString(vkFormat) <<
", Color Space: " << colorSpace << std::endl;
counter++;
}
}
The output I receive is limited to:
[0] Format: VK_FORMAT_R8G8B8A8_UNORM, Color Space: 0
[1] Format: VK_FORMAT_B8G8R8A8_UNORM, Color Space: 0
[2] Format: VK_FORMAT_R8G8B8A8_SRGB, Color Space: 0
[3] Format: VK_FORMAT_B8G8R8A8_SRGB, Color Space: 0
This looks incorrect because I am using a powerful AMD GPU (Radeon), which supports compressed formats like "VK_FORMAT_BC1_RGBA_UNORM_BLOCK." This is evident because I can successfully create an image using this format:
imageInfo.format = VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
imageInfo.tiling = tiling;
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
imageInfo.usage = usage;
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
if (vkCreateImage(device, &imageInfo, nullptr, &image) != VK_SUCCESS) {
throw std::runtime_error("failed to create image!");
}
I suspect my previous code only enumerates KHR Surface capabilities and not the GPU texture formats.
In summary, how can I query the available GPU texture formats?
Thank you very much for your assistance.
vkGetPhysicalDeviceSurfaceFormatsKHR
is only for querying the GPUs supported formats for a surface as part of VK_KHR_surface.
Querying support for image formats can be done with vkGetPhysicalDeviceFormatProperties
archive.
void IterateFormats(VkFormat min, VkFormat max)
{
for(VkFormat fmt = min; fmt <= max; ++fmt)
{
VkFormatProperties properties{};
vkGetPhysicalDeviceFormatProperties(device, fmt, &properties);
SaveFormat(fmt, properties);
}
}
void IterateFormatGroups()
{
// VK_VERSION_1_0
IterateFormats(VK_FORMAT_R4G4_UNORM_PACK8, VK_FORMAT_ASTC_12x12_SRGB_BLOCK);
// VK_VERSION_1_1, VK_KHR_sampler_ycbcr_conversion
IterateFormats(VK_FORMAT_G8B8G8R8_422_UNORM, VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM);
// VK_VERSION_1_3, VK_EXT_ycbcr_2plane_444_formats
IterateFormats(VK_FORMAT_G8_B8R8_2PLANE_444_UNORM, VK_FORMAT_G16_B16R16_2PLANE_444_UNORM);
// VK_VERSION_1_3, VK_EXT_4444_formats
IterateFormats(VK_FORMAT_A4R4G4B4_UNORM_PACK16, VK_FORMAT_A4B4G4R4_UNORM_PACK16);
// VK_VERSION_1_3, VK_EXT_texture_compression_astc_hdr
IterateFormats(VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK, VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK);
// VK_IMG_format_pvrtc
IterateFormats(VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG);
// VK_NV_optical_flow
IterateFormats(VK_FORMAT_R16G16_SFIXED5_NV, VK_FORMAT_R16G16_SFIXED5_NV);
// VK_KHR_maintenance5
IterateFormats(VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR, VK_FORMAT_A8_UNORM_KHR);
}