vulkan: Add function to query format and modifier information

This commit is contained in:
columbarius 2023-08-11 22:59:22 +02:00 committed by Wim Taymans
parent cf0e3a35ba
commit 58853eb2c7
4 changed files with 165 additions and 2 deletions

View file

@ -539,8 +539,11 @@ int spa_vulkan_process(struct vulkan_compute_state *s)
int spa_vulkan_init(struct vulkan_compute_state *s)
{
s->base.log = s->log;
uint32_t dsp_format = SPA_VIDEO_FORMAT_DSP_F32;
struct vulkan_base_info baseInfo = {
.queueFlags = VK_QUEUE_COMPUTE_BIT,
.formatInfo.formatCount = 1,
.formatInfo.formats = &dsp_format,
};
return vulkan_base_init(&s->base, &baseInfo);
}

View file

@ -7,6 +7,18 @@
#define MAX_BUFFERS 16
struct vulkan_modifier_info {
VkDrmFormatModifierPropertiesEXT props;
VkExtent2D max_extent;
};
struct vulkan_format_info {
uint32_t spa_format;
VkFormat vk_format;
uint32_t modifierCount;
struct vulkan_modifier_info *infos;
};
struct vulkan_buffer {
int fd;
VkImage image;
@ -28,6 +40,11 @@ struct vulkan_stream {
struct vulkan_base_info {
uint32_t queueFlags;
struct {
uint32_t formatCount;
uint32_t *formats;
} formatInfo;
};
struct vulkan_base {
@ -41,5 +58,8 @@ struct vulkan_base {
uint32_t queueFamilyIndex;
VkDevice device;
uint32_t formatInfoCount;
struct vulkan_format_info *formatInfos;
unsigned int initialized:1;
};

View file

@ -200,13 +200,15 @@ static int createDevice(struct vulkan_base *s, struct vulkan_base_info *info)
};
static const char * const extensions[] = {
VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME
VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME,
VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME
};
const VkDeviceCreateInfo deviceCreateInfo = {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.queueCreateInfoCount = 1,
.pQueueCreateInfos = &queueCreateInfo,
.enabledExtensionCount = 2,
.enabledExtensionCount = SPA_N_ELEMENTS(extensions),
.ppEnabledExtensionNames = extensions,
};
@ -217,6 +219,110 @@ static int createDevice(struct vulkan_base *s, struct vulkan_base_info *info)
return 0;
}
static int queryFormatInfo(struct vulkan_base *s, struct vulkan_base_info *info)
{
if (s->formatInfos)
return 0;
s->formatInfos = calloc(info->formatInfo.formatCount, sizeof(struct vulkan_format_info));
if (!s->formatInfos)
return -ENOMEM;
for (uint32_t i = 0; i < info->formatInfo.formatCount; i++) {
VkFormat format = vulkan_id_to_vkformat(info->formatInfo.formats[i]);
if (format == VK_FORMAT_UNDEFINED)
continue;
struct vulkan_format_info *f_info = &s->formatInfos[s->formatInfoCount++];
f_info->spa_format = info->formatInfo.formats[i];
f_info->vk_format = format;
VkDrmFormatModifierPropertiesListEXT modPropsList = {
.sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
};
VkFormatProperties2 fmtProps = {
.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
.pNext = &modPropsList,
};
vkGetPhysicalDeviceFormatProperties2(s->physicalDevice, format, &fmtProps);
if (!modPropsList.drmFormatModifierCount)
continue;
modPropsList.pDrmFormatModifierProperties = calloc(modPropsList.drmFormatModifierCount,
sizeof(modPropsList.pDrmFormatModifierProperties[0]));
if (!modPropsList.pDrmFormatModifierProperties)
continue;
vkGetPhysicalDeviceFormatProperties2(s->physicalDevice, format, &fmtProps);
f_info->infos = calloc(modPropsList.drmFormatModifierCount, sizeof(f_info->infos[0]));
if (!f_info->infos) {
free(modPropsList.pDrmFormatModifierProperties);
continue;
}
for (uint32_t j = 0; j < modPropsList.drmFormatModifierCount; j++) {
VkDrmFormatModifierPropertiesEXT props = modPropsList.pDrmFormatModifierProperties[j];
if (!(props.drmFormatModifierTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
continue;
VkPhysicalDeviceImageDrmFormatModifierInfoEXT modInfo = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
.drmFormatModifier = props.drmFormatModifier,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
};
VkPhysicalDeviceExternalImageFormatInfo extImgFmtInfo = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
.pNext = &modInfo,
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
};
VkPhysicalDeviceImageFormatInfo2 imgFmtInfo = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
.pNext = &extImgFmtInfo,
.type = VK_IMAGE_TYPE_2D,
.format = format,
.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
};
VkExternalImageFormatProperties extImgFmtProps = {
.sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
};
VkImageFormatProperties2 imgFmtProps = {
.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
.pNext = &extImgFmtProps,
};
VK_CHECK_RESULT_LOOP(vkGetPhysicalDeviceImageFormatProperties2(s->physicalDevice, &imgFmtInfo, &imgFmtProps))
VkExternalMemoryFeatureFlags extMemFeatures =
extImgFmtProps.externalMemoryProperties.externalMemoryFeatures;
if (!(extMemFeatures & VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT)) {
continue;
}
VkExtent3D max_extent = imgFmtProps.imageFormatProperties.maxExtent;
f_info->infos[f_info->modifierCount++] = (struct vulkan_modifier_info){
.props = props,
.max_extent = { .width = max_extent.width, .height = max_extent.height },
};
}
free(modPropsList.pDrmFormatModifierProperties);
}
return 0;
}
static void destroyFormatInfo(struct vulkan_base *s)
{
for (uint32_t i = 0; i < s->formatInfoCount; i++) {
free(s->formatInfos[i].infos);
}
free(s->formatInfos);
s->formatInfos = NULL;
s->formatInfoCount = 0;
}
int vulkan_commandPool_create(struct vulkan_base *s, VkCommandPool *commandPool)
{
const VkCommandPoolCreateInfo commandPoolCreateInfo = {
@ -262,6 +368,27 @@ uint32_t vulkan_memoryType_find(struct vulkan_base *s,
return -1;
}
struct vulkan_format_info *vulkan_formatInfo_find(struct vulkan_base *s, VkFormat format)
{
for (uint32_t i = 0; i < s->formatInfoCount; i++) {
if (s->formatInfos[i].vk_format == format)
return &s->formatInfos[i];
}
return NULL;
}
struct vulkan_modifier_info *vulkan_modifierInfo_find(struct vulkan_base *s, VkFormat format, uint64_t mod)
{
struct vulkan_format_info *f_info = vulkan_formatInfo_find(s, format);
if (!f_info)
return NULL;
for (uint32_t i = 0; i < f_info->modifierCount; i++) {
if (f_info->infos[i].props.drmFormatModifier == mod)
return &f_info->infos[i];
}
return NULL;
}
void vulkan_buffer_clear(struct vulkan_base *s, struct vulkan_buffer *buffer)
{
if (buffer->fd != -1)
@ -311,6 +438,7 @@ int vulkan_base_init(struct vulkan_base *s, struct vulkan_base_info *info)
CHECK(createInstance(s));
CHECK(findPhysicalDevice(s));
CHECK(createDevice(s, info));
CHECK(queryFormatInfo(s, info));
s->initialized = true;
}
return 0;
@ -319,6 +447,7 @@ int vulkan_base_init(struct vulkan_base *s, struct vulkan_base_info *info)
void vulkan_base_deinit(struct vulkan_base *s)
{
if (s->initialized) {
destroyFormatInfo(s);
vkDestroyDevice(s->device, NULL);
vkDestroyInstance(s->instance, NULL);
s->initialized = false;

View file

@ -18,6 +18,15 @@
return _r; \
} \
}
#define VK_CHECK_RESULT_LOOP(f) \
{ \
VkResult _result = (f); \
int _r = -vkresult_to_errno(_result); \
if (_result != VK_SUCCESS) { \
spa_log_error(s->log, "error: %d (%d %s)", _result, _r, spa_strerror(_r)); \
continue; \
} \
}
#define CHECK(f) \
{ \
int _res = (f); \
@ -30,6 +39,8 @@ int vulkan_commandBuffer_create(struct vulkan_base *s, VkCommandPool commandPool
uint32_t vulkan_memoryType_find(struct vulkan_base *s,
uint32_t memoryTypeBits, VkMemoryPropertyFlags properties);
struct vulkan_format_info *vulkan_formatInfo_find(struct vulkan_base *s, VkFormat format);
struct vulkan_modifier_info *vulkan_modifierInfo_find(struct vulkan_base *s, VkFormat format, uint64_t modifier);
void vulkan_buffer_clear(struct vulkan_base *s, struct vulkan_buffer *buffer);