vulkan: move format enumeration into utils functions

This splots the format enumeration into a helper for dsp and raw pod
creation and a common function for the compute filters.

Counting formats with modifiers will be usefull to announce dsp and
raw formats from the same node.

No functional changes.
This commit is contained in:
columbarius 2023-09-23 14:32:46 +02:00 committed by Wim Taymans
parent 02779fe28b
commit 49b67742c6
10 changed files with 276 additions and 274 deletions

View file

@ -3,7 +3,8 @@ spa_vulkan_sources = [
'vulkan-compute-filter.c',
'vulkan-compute-source.c',
'vulkan-compute-utils.c',
'vulkan-utils.c'
'vulkan-utils.c',
'utils.c',
]
drm = dependency('libdrm')

View file

@ -0,0 +1,91 @@
/* Spa */
/* SPDX-FileCopyrightText: Copyright © 2023 columbarius */
/* SPDX-License-Identifier: MIT */
#include "utils.h"
#include <spa/param/param.h>
#include <spa/param/video/dsp.h>
#include <spa/param/video/raw.h>
// This function enumerates the available formats in vulkan_state::formats, announcing all formats capable to support DmaBufs
// first and then falling back to those supported with SHM buffers.
bool find_EnumFormatInfo(struct vulkan_format_infos *fmtInfos, uint32_t index, uint32_t caps, uint32_t *fmt_idx, bool *has_modifier)
{
int64_t fmtIterator = 0;
int64_t maxIterator = 0;
if (caps & VULKAN_BUFFER_TYPE_CAP_SHM)
maxIterator += fmtInfos->formatCount;
if (caps & VULKAN_BUFFER_TYPE_CAP_DMABUF)
maxIterator += fmtInfos->formatCount;
// Count available formats until index underflows, while fmtIterator indexes the current format.
// Iterate twice over formats first time with modifiers, second time without if both caps are supported.
while (index < (uint32_t)-1 && fmtIterator < maxIterator) {
const struct vulkan_format_info *f_info = &fmtInfos->infos[fmtIterator%fmtInfos->formatCount];
if (caps & VULKAN_BUFFER_TYPE_CAP_DMABUF && fmtIterator < fmtInfos->formatCount) {
// First round, check for modifiers
if (f_info->modifierCount > 0) {
index--;
}
} else if (caps & VULKAN_BUFFER_TYPE_CAP_SHM) {
// Second round, every format should be supported.
index--;
}
fmtIterator++;
}
if (index != (uint32_t)-1) {
// No more formats available
return false;
}
// Undo end of loop increment
fmtIterator--;
*fmt_idx = fmtIterator%fmtInfos->formatCount;
// Loop finished in first round
*has_modifier = caps & VULKAN_BUFFER_TYPE_CAP_DMABUF && fmtIterator < fmtInfos->formatCount;
return true;
}
struct spa_pod *build_dsp_EnumFormat(const struct vulkan_format_info *fmt, bool with_modifiers, struct spa_pod_builder *builder)
{
struct spa_pod_frame f[2];
uint32_t i, c;
spa_pod_builder_push_object(builder, &f[0], SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
spa_pod_builder_add(builder, SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), 0);
spa_pod_builder_add(builder, SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp), 0);
spa_pod_builder_add(builder, SPA_FORMAT_VIDEO_format, SPA_POD_Id(fmt->spa_format), 0);
if (with_modifiers && fmt->modifierCount > 0) {
spa_pod_builder_prop(builder, SPA_FORMAT_VIDEO_modifier, SPA_POD_PROP_FLAG_MANDATORY | SPA_POD_PROP_FLAG_DONT_FIXATE);
spa_pod_builder_push_choice(builder, &f[1], SPA_CHOICE_Enum, 0);
for (i = 0, c = 0; i < fmt->modifierCount; i++) {
spa_pod_builder_long(builder, fmt->infos[i].props.drmFormatModifier);
if (c++ == 0)
spa_pod_builder_long(builder, fmt->infos[i].props.drmFormatModifier);
}
spa_pod_builder_pop(builder, &f[1]);
}
return spa_pod_builder_pop(builder, &f[0]);
}
struct spa_pod *build_raw_EnumFormat(const struct vulkan_format_info *fmt, bool with_modifiers, struct spa_pod_builder *builder)
{
struct spa_pod_frame f[2];
uint32_t i, c;
spa_pod_builder_push_object(builder, &f[0], SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
spa_pod_builder_add(builder, SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), 0);
spa_pod_builder_add(builder, SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), 0);
spa_pod_builder_add(builder, SPA_FORMAT_VIDEO_format, SPA_POD_Id(fmt->spa_format), 0);
if (with_modifiers && fmt->modifierCount > 0) {
spa_pod_builder_prop(builder, SPA_FORMAT_VIDEO_modifier, SPA_POD_PROP_FLAG_MANDATORY | SPA_POD_PROP_FLAG_DONT_FIXATE);
spa_pod_builder_push_choice(builder, &f[1], SPA_CHOICE_Enum, 0);
for (i = 0, c = 0; i < fmt->modifierCount; i++) {
spa_pod_builder_long(builder, fmt->infos[i].props.drmFormatModifier);
if (c++ == 0)
spa_pod_builder_long(builder, fmt->infos[i].props.drmFormatModifier);
}
spa_pod_builder_pop(builder, &f[1]);
}
return spa_pod_builder_pop(builder, &f[0]);
}

View file

@ -0,0 +1,11 @@
/* Spa */
/* SPDX-FileCopyrightText: Copyright © 2023 columbarius */
/* SPDX-License-Identifier: MIT */
#include "vulkan-types.h"
#include "spa/pod/builder.h"
bool find_EnumFormatInfo(struct vulkan_format_infos *fmtInfos, uint32_t index, uint32_t caps, uint32_t *fmt_idx, bool *has_modifier);
struct spa_pod *build_dsp_EnumFormat(const struct vulkan_format_info *fmt, bool with_modifiers, struct spa_pod_builder *builder);
struct spa_pod *build_raw_EnumFormat(const struct vulkan_format_info *fmt, bool with_modifiers, struct spa_pod_builder *builder);

View file

@ -269,64 +269,6 @@ impl_node_remove_port(void *object, enum spa_direction direction, uint32_t port_
return -ENOTSUP;
}
static struct spa_pod *build_EnumFormat(uint32_t fmt, const struct vulkan_format_info *fmtInfo, struct spa_pod_builder *builder) {
struct spa_pod_frame f[2];
uint32_t i, c;
spa_pod_builder_push_object(builder, &f[0], SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
spa_pod_builder_add(builder, SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), 0);
spa_pod_builder_add(builder, SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp), 0);
spa_pod_builder_add(builder, SPA_FORMAT_VIDEO_format, SPA_POD_Id(fmt), 0);
if (fmtInfo && fmtInfo->modifierCount > 0) {
spa_pod_builder_prop(builder, SPA_FORMAT_VIDEO_modifier, SPA_POD_PROP_FLAG_MANDATORY | SPA_POD_PROP_FLAG_DONT_FIXATE);
spa_pod_builder_push_choice(builder, &f[1], SPA_CHOICE_Enum, 0);
for (i = 0, c = 0; i < fmtInfo->modifierCount; i++) {
spa_pod_builder_long(builder, fmtInfo->infos[i].props.drmFormatModifier);
if (c++ == 0)
spa_pod_builder_long(builder, fmtInfo->infos[i].props.drmFormatModifier);
}
spa_pod_builder_pop(builder, &f[1]);
}
return spa_pod_builder_pop(builder, &f[0]);
}
// This function enumerates the available formats in vulkan_state::formats, announcing all formats capable to support DmaBufs
// first and then falling back to those supported with SHM buffers.
static bool find_EnumFormatInfo(struct vulkan_base *s, uint32_t index, uint32_t caps, uint32_t *fmt_idx, bool *has_modifier) {
int64_t fmtIterator = 0;
int64_t maxIterator = 0;
if (caps & VULKAN_BUFFER_TYPE_CAP_SHM)
maxIterator += s->formatInfoCount;
if (caps & VULKAN_BUFFER_TYPE_CAP_DMABUF)
maxIterator += s->formatInfoCount;
// Count available formats until index underflows, while fmtIterator indexes the current format.
// Iterate twice over formats first time with modifiers, second time without if both caps are supported.
while (index < (uint32_t)-1 && fmtIterator < maxIterator) {
const struct vulkan_format_info *f_info = &s->formatInfos[fmtIterator%s->formatInfoCount];
if (caps & VULKAN_BUFFER_TYPE_CAP_DMABUF && fmtIterator < s->formatInfoCount) {
// First round, check for modifiers
if (f_info->modifierCount > 0) {
index--;
}
} else if (caps & VULKAN_BUFFER_TYPE_CAP_SHM) {
// Second round, every format should be supported.
index--;
}
fmtIterator++;
}
if (index != (uint32_t)-1) {
// No more formats available
return false;
}
// Undo end of loop increment
fmtIterator--;
*fmt_idx = fmtIterator%s->formatInfoCount;
// Loop finished in first round
*has_modifier = caps & VULKAN_BUFFER_TYPE_CAP_DMABUF && fmtIterator < s->formatInfoCount;
return true;
}
static int port_enum_formats(void *object,
enum spa_direction direction, uint32_t port_id,
uint32_t index,
@ -336,8 +278,6 @@ static int port_enum_formats(void *object,
{
struct impl *this = object;
uint32_t fmt_index;
bool has_modifier;
if (this->port[port_id].have_format
&& this->port[port_id].current_format.info.dsp.flags & SPA_VIDEO_FLAG_MODIFIER
&& this->port[port_id].current_format.info.dsp.flags ^ SPA_VIDEO_FLAG_MODIFIER_FIXATION_REQUIRED) {
@ -347,18 +287,10 @@ static int port_enum_formats(void *object,
*param = spa_format_video_dsp_build(builder, SPA_PARAM_EnumFormat, &this->port[port_id].current_format.info.dsp);
return 1;
}
if (!find_EnumFormatInfo(&this->state.base, index-1, spa_vulkan_compute_get_buffer_caps(&this->state, direction), &fmt_index, &has_modifier))
return 0;
return spa_vulkan_compute_enumerate_formats(&this->state, index-1, spa_vulkan_compute_get_buffer_caps(&this->state, direction), param, builder);
} else {
if (!find_EnumFormatInfo(&this->state.base, index, spa_vulkan_compute_get_buffer_caps(&this->state, direction), &fmt_index, &has_modifier))
return 0;
return spa_vulkan_compute_enumerate_formats(&this->state, index, spa_vulkan_compute_get_buffer_caps(&this->state, direction), param, builder);
}
const struct vulkan_format_info *f_info = &this->state.base.formatInfos[fmt_index];
spa_log_info(this->log, "vulkan-compute-filter: enum_formats idx: %d, format %d, has_modifier %d", index, f_info->spa_format, has_modifier);
*param = build_EnumFormat(f_info->spa_format, has_modifier ? f_info : NULL, builder);
return 1;
}
static int

View file

@ -503,64 +503,6 @@ impl_node_remove_port(void *object, enum spa_direction direction, uint32_t port_
return -ENOTSUP;
}
static struct spa_pod *build_EnumFormat(uint32_t fmt, const struct vulkan_format_info *fmtInfo, struct spa_pod_builder *builder) {
struct spa_pod_frame f[2];
uint32_t i, c;
spa_pod_builder_push_object(builder, &f[0], SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
spa_pod_builder_add(builder, SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), 0);
spa_pod_builder_add(builder, SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp), 0);
spa_pod_builder_add(builder, SPA_FORMAT_VIDEO_format, SPA_POD_Id(fmt), 0);
if (fmtInfo && fmtInfo->modifierCount > 0) {
spa_pod_builder_prop(builder, SPA_FORMAT_VIDEO_modifier, SPA_POD_PROP_FLAG_MANDATORY | SPA_POD_PROP_FLAG_DONT_FIXATE);
spa_pod_builder_push_choice(builder, &f[1], SPA_CHOICE_Enum, 0);
for (i = 0, c = 0; i < fmtInfo->modifierCount; i++) {
spa_pod_builder_long(builder, fmtInfo->infos[i].props.drmFormatModifier);
if (c++ == 0)
spa_pod_builder_long(builder, fmtInfo->infos[i].props.drmFormatModifier);
}
spa_pod_builder_pop(builder, &f[1]);
}
return spa_pod_builder_pop(builder, &f[0]);
}
// This function enumerates the available formats in vulkan_state::formats, announcing all formats capable to support DmaBufs
// first and then falling back to those supported with SHM buffers.
static bool find_EnumFormatInfo(struct vulkan_base *s, uint32_t index, uint32_t caps, uint32_t *fmt_idx, bool *has_modifier) {
int64_t fmtIterator = 0;
int64_t maxIterator = 0;
if (caps & VULKAN_BUFFER_TYPE_CAP_SHM)
maxIterator += s->formatInfoCount;
if (caps & VULKAN_BUFFER_TYPE_CAP_DMABUF)
maxIterator += s->formatInfoCount;
// Count available formats until index underflows, while fmtIterator indexes the current format.
// Iterate twice over formats first time with modifiers, second time without if both caps are supported.
while (index < (uint32_t)-1 && fmtIterator < maxIterator) {
const struct vulkan_format_info *f_info = &s->formatInfos[fmtIterator%s->formatInfoCount];
if (caps & VULKAN_BUFFER_TYPE_CAP_DMABUF && fmtIterator < s->formatInfoCount) {
// First round, check for modifiers
if (f_info->modifierCount > 0) {
index--;
}
} else if (caps & VULKAN_BUFFER_TYPE_CAP_SHM) {
// Second round, every format should be supported.
index--;
}
fmtIterator++;
}
if (index != (uint32_t)-1) {
// No more formats available
return false;
}
// Undo end of loop increment
fmtIterator--;
*fmt_idx = fmtIterator%s->formatInfoCount;
// Loop finished in first round
*has_modifier = caps & VULKAN_BUFFER_TYPE_CAP_DMABUF && fmtIterator < s->formatInfoCount;
return true;
}
static int port_enum_formats(void *object,
enum spa_direction direction, uint32_t port_id,
uint32_t index,
@ -570,8 +512,6 @@ static int port_enum_formats(void *object,
{
struct impl *this = object;
uint32_t fmt_index;
bool has_modifier;
if (this->port.have_format
&& this->port.current_format.info.dsp.flags & SPA_VIDEO_FLAG_MODIFIER
&& this->port.current_format.info.dsp.flags ^ SPA_VIDEO_FLAG_MODIFIER_FIXATION_REQUIRED) {
@ -581,18 +521,10 @@ static int port_enum_formats(void *object,
*param = spa_format_video_dsp_build(builder, SPA_PARAM_EnumFormat, &this->port.current_format.info.dsp);
return 1;
}
if (!find_EnumFormatInfo(&this->state.base, index-1, spa_vulkan_compute_get_buffer_caps(&this->state, direction), &fmt_index, &has_modifier))
return 0;
return spa_vulkan_compute_enumerate_formats(&this->state, index-1, spa_vulkan_compute_get_buffer_caps(&this->state, direction), param, builder);
} else {
if (!find_EnumFormatInfo(&this->state.base, index, spa_vulkan_compute_get_buffer_caps(&this->state, direction), &fmt_index, &has_modifier))
return 0;
return spa_vulkan_compute_enumerate_formats(&this->state, index, spa_vulkan_compute_get_buffer_caps(&this->state, direction), param, builder);
}
const struct vulkan_format_info *f_info = &this->state.base.formatInfos[fmt_index];
spa_log_info(this->log, "vulkan-compute-source: enum_formats idx: %d, format %d, has_modifier %d", index, f_info->spa_format, has_modifier);
*param = build_EnumFormat(f_info->spa_format, has_modifier ? f_info : NULL, builder);
return 1;
}
static int

View file

@ -27,6 +27,7 @@
#include "vulkan-compute-utils.h"
#include "vulkan-utils.h"
#include "utils.h"
#define VULKAN_INSTANCE_FUNCTION(name) \
PFN_##name name = (PFN_##name)vkGetInstanceProcAddr(s->base.instance, #name)
@ -495,7 +496,7 @@ int spa_vulkan_compute_use_buffers(struct vulkan_compute_state *s, struct vulkan
: VK_IMAGE_USAGE_SAMPLED_BIT,
.spa_buf = buffers[i],
};
struct vulkan_modifier_info *modifierInfo = vulkan_modifierInfo_find(&s->base, format, dsp_info->modifier);
struct vulkan_modifier_info *modifierInfo = vulkan_modifierInfo_find(&s->formatInfos, format, dsp_info->modifier);
CHECK(vulkan_validate_dmabuf_properties(modifierInfo, &dmabufInfo.spa_buf->n_datas, &dmabufInfo.size));
ret = vulkan_create_dmabuf(&s->base, &dmabufInfo, &p->buffers[i]);
} else {
@ -515,7 +516,7 @@ int spa_vulkan_compute_use_buffers(struct vulkan_compute_state *s, struct vulkan
: VK_IMAGE_USAGE_SAMPLED_BIT,
.spa_buf = buffers[i],
};
struct vulkan_modifier_info *modifierInfo = vulkan_modifierInfo_find(&s->base, format, dsp_info->modifier);
struct vulkan_modifier_info *modifierInfo = vulkan_modifierInfo_find(&s->formatInfos, format, dsp_info->modifier);
CHECK(vulkan_validate_dmabuf_properties(modifierInfo, &dmabufInfo.spa_buf->n_datas, &dmabufInfo.size));
ret = vulkan_import_dmabuf(&s->base, &dmabufInfo, &p->buffers[i]);
break;
@ -547,6 +548,17 @@ int spa_vulkan_compute_use_buffers(struct vulkan_compute_state *s, struct vulkan
return 0;
}
int spa_vulkan_compute_enumerate_formats(struct vulkan_compute_state *s, uint32_t index, uint32_t caps,
struct spa_pod **param, struct spa_pod_builder *builder)
{
uint32_t fmt_idx;
bool has_modifier;
if (!find_EnumFormatInfo(&s->formatInfos, index, caps, &fmt_idx, &has_modifier))
return 0;
*param = build_dsp_EnumFormat(&s->formatInfos.infos[fmt_idx], has_modifier, builder);
return 1;
}
static int vulkan_stream_init(struct vulkan_stream *stream, enum spa_direction direction,
struct spa_dict *props)
{
@ -659,22 +671,27 @@ int spa_vulkan_compute_get_buffer_caps(struct vulkan_compute_state *s, enum spa_
struct vulkan_modifier_info *spa_vulkan_compute_get_modifier_info(struct vulkan_compute_state *s, struct spa_video_info_dsp *info) {
VkFormat vk_format = vulkan_id_to_vkformat(info->format);
return vulkan_modifierInfo_find(&s->base, vk_format, info->modifier);
return vulkan_modifierInfo_find(&s->formatInfos, vk_format, info->modifier);
}
int spa_vulkan_compute_init(struct vulkan_compute_state *s)
{
int ret;
s->base.log = s->log;
uint32_t dsp_format = SPA_VIDEO_FORMAT_DSP_F32;
uint32_t dsp_formats[] = {
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);
if ((ret = vulkan_base_init(&s->base, &baseInfo)) < 0)
return ret;
return vulkan_format_infos_init(&s->base, SPA_N_ELEMENTS(dsp_formats), dsp_formats, &s->formatInfos);
}
void spa_vulkan_compute_deinit(struct vulkan_compute_state *s)
{
vulkan_format_infos_deinit(&s->formatInfos);
vulkan_base_deinit(&s->base);
}

View file

@ -7,6 +7,7 @@
#include <spa/buffer/buffer.h>
#include <spa/param/video/format.h>
#include <spa/node/node.h>
#include <spa/pod/builder.h>
#include "vulkan-utils.h"
@ -44,6 +45,8 @@ struct vulkan_compute_state {
struct vulkan_base base;
struct vulkan_format_infos formatInfos;
VkPipeline pipeline;
VkPipelineLayout pipelineLayout;
const char *shaderName;
@ -73,9 +76,11 @@ int spa_vulkan_compute_init_stream(struct vulkan_compute_state *s, struct vulkan
int spa_vulkan_compute_fixate_modifier(struct vulkan_compute_state *s, struct vulkan_stream *p, struct spa_video_info_dsp *dsp_info,
uint32_t modifierCount, uint64_t *modifiers, uint64_t *modifier);
int spa_vulkan_compute_prepare(struct vulkan_compute_state *s);
int spa_vulkan_compute_use_buffers(struct vulkan_compute_state *s, struct vulkan_stream *stream, uint32_t flags,
struct spa_video_info_dsp *dsp_info, uint32_t n_buffers, struct spa_buffer **buffers);
int spa_vulkan_compute_enumerate_formats(struct vulkan_compute_state *s, uint32_t index, uint32_t caps,
struct spa_pod **param, struct spa_pod_builder *builder);
int spa_vulkan_compute_prepare(struct vulkan_compute_state *s);
int spa_vulkan_compute_unprepare(struct vulkan_compute_state *s);
int spa_vulkan_compute_start(struct vulkan_compute_state *s);

View file

@ -25,6 +25,13 @@ struct vulkan_format_info {
struct vulkan_modifier_info *infos;
};
struct vulkan_format_infos {
uint32_t formatCount;
struct vulkan_format_info *infos;
uint32_t formatsWithModifiersCount;
};
struct vulkan_buffer {
int fd;
VkImage image;
@ -35,11 +42,6 @@ struct vulkan_buffer {
struct vulkan_base_info {
uint32_t queueFlags;
struct {
uint32_t formatCount;
uint32_t *formats;
} formatInfo;
};
struct vulkan_base {
@ -53,9 +55,6 @@ struct vulkan_base {
uint32_t queueFamilyIndex;
VkDevice device;
uint32_t formatInfoCount;
struct vulkan_format_info *formatInfos;
bool implicit_sync_interop;
unsigned int initialized:1;

View file

@ -233,113 +233,6 @@ 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;
if (props.drmFormatModifierPlaneCount > DMABUF_MAX_PLANES)
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_read_pixels(struct vulkan_base *s, struct vulkan_read_pixels_info *info, struct vulkan_buffer *vk_buf)
{
VkImageSubresource img_sub_res = {
@ -478,18 +371,18 @@ uint32_t vulkan_memoryType_find(struct vulkan_base *s,
return -1;
}
struct vulkan_format_info *vulkan_formatInfo_find(struct vulkan_base *s, VkFormat format)
struct vulkan_format_info *vulkan_formatInfo_find(struct vulkan_format_infos *fmtInfo, VkFormat format)
{
for (uint32_t i = 0; i < s->formatInfoCount; i++) {
if (s->formatInfos[i].vk_format == format)
return &s->formatInfos[i];
for (uint32_t i = 0; i < fmtInfo->formatCount; i++) {
if (fmtInfo->infos[i].vk_format == format)
return &fmtInfo->infos[i];
}
return NULL;
}
struct vulkan_modifier_info *vulkan_modifierInfo_find(struct vulkan_base *s, VkFormat format, uint64_t mod)
struct vulkan_modifier_info *vulkan_modifierInfo_find(struct vulkan_format_infos *fmtInfo, VkFormat format, uint64_t mod)
{
struct vulkan_format_info *f_info = vulkan_formatInfo_find(s, format);
struct vulkan_format_info *f_info = vulkan_formatInfo_find(fmtInfo, format);
if (!f_info)
return NULL;
for (uint32_t i = 0; i < f_info->modifierCount; i++) {
@ -865,13 +758,132 @@ int vulkan_wait_idle(struct vulkan_base *s)
return 0;
}
int vulkan_format_infos_init(struct vulkan_base *s, uint32_t formatCount, uint32_t *formats,
struct vulkan_format_infos *info)
{
if (info->infos)
return 0;
info->infos = calloc(formatCount, sizeof(struct vulkan_format_info));
if (!info->infos)
return -ENOMEM;
uint32_t i;
for (i = 0; i < formatCount; i++) {
VkFormat format = vulkan_id_to_vkformat(formats[i]);
if (format == VK_FORMAT_UNDEFINED)
continue;
struct vulkan_format_info *f_info = &info->infos[info->formatCount++];
f_info->spa_format = formats[i];
f_info->vk_format = format;
spa_log_info(s->log, "Adding format %d (spa_format %d)", format, formats[i]);
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 == 0) {
spa_log_info(s->log, "Format has no modifiers");
continue;
}
modPropsList.pDrmFormatModifierProperties = calloc(modPropsList.drmFormatModifierCount,
sizeof(modPropsList.pDrmFormatModifierProperties[0]));
if (!modPropsList.pDrmFormatModifierProperties) {
spa_log_info(s->log, "Failed to allocate DrmFormatModifierProperties");
continue;
}
vkGetPhysicalDeviceFormatProperties2(s->physicalDevice, format, &fmtProps);
f_info->infos = calloc(modPropsList.drmFormatModifierCount, sizeof(f_info->infos[0]));
if (!f_info->infos) {
spa_log_info(s->log, "Failed to allocate modifier infos");
free(modPropsList.pDrmFormatModifierProperties);
continue;
}
spa_log_info(s->log, "Found %d modifiers", modPropsList.drmFormatModifierCount);
for (uint32_t j = 0; j < modPropsList.drmFormatModifierCount; j++) {
VkDrmFormatModifierPropertiesEXT props = modPropsList.pDrmFormatModifierProperties[j];
if (!(props.drmFormatModifierTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
continue;
if (props.drmFormatModifierPlaneCount > DMABUF_MAX_PLANES)
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 },
};
spa_log_info(s->log, "Adding modifier %"PRIu64, props.drmFormatModifier);
}
free(modPropsList.pDrmFormatModifierProperties);
}
for (i = 0; i < info->formatCount; i++) {
if (info->infos[i].modifierCount > 0)
info->formatsWithModifiersCount++;
}
return 0;
}
void vulkan_format_infos_deinit(struct vulkan_format_infos *info)
{
for (uint32_t i = 0; i < info->formatCount; i++) {
free(info->infos[i].infos);
}
free(info->infos);
}
int vulkan_base_init(struct vulkan_base *s, struct vulkan_base_info *info)
{
if (!s->initialized) {
CHECK(createInstance(s));
CHECK(findPhysicalDevice(s));
CHECK(createDevice(s, info));
CHECK(queryFormatInfo(s, info));
s->implicit_sync_interop = dmabuf_check_sync_file_import_export(s->log);
s->initialized = true;
}
@ -881,7 +893,6 @@ 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

@ -87,8 +87,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);
struct vulkan_format_info *vulkan_formatInfo_find(struct vulkan_format_infos *fmtInfo, VkFormat format);
struct vulkan_modifier_info *vulkan_modifierInfo_find(struct vulkan_format_infos *fmtInfo, VkFormat format, uint64_t modifier);
void vulkan_buffer_clear(struct vulkan_base *s, struct vulkan_buffer *buffer);
@ -100,5 +100,8 @@ int vulkan_vkresult_to_errno(VkResult result);
int vulkan_wait_fence(struct vulkan_base *s, VkFence fence);
int vulkan_wait_idle(struct vulkan_base *s);
int vulkan_format_infos_init(struct vulkan_base *s, uint32_t formatCount, uint32_t *formats,
struct vulkan_format_infos *info);
void vulkan_format_infos_deinit(struct vulkan_format_infos *info);
int vulkan_base_init(struct vulkan_base *s, struct vulkan_base_info *info);
void vulkan_base_deinit(struct vulkan_base *s);