mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-01 22:58:50 -04:00
vulkan: Add function to query format and modifier information
This commit is contained in:
parent
cf0e3a35ba
commit
58853eb2c7
4 changed files with 165 additions and 2 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue