From 49b67742c67125b9c1e234c21e453b689399fa02 Mon Sep 17 00:00:00 2001 From: columbarius Date: Sat, 23 Sep 2023 14:32:46 +0200 Subject: [PATCH] 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. --- spa/plugins/vulkan/meson.build | 3 +- spa/plugins/vulkan/utils.c | 91 ++++++++ spa/plugins/vulkan/utils.h | 11 + spa/plugins/vulkan/vulkan-compute-filter.c | 72 +----- spa/plugins/vulkan/vulkan-compute-source.c | 72 +----- spa/plugins/vulkan/vulkan-compute-utils.c | 31 ++- spa/plugins/vulkan/vulkan-compute-utils.h | 7 +- spa/plugins/vulkan/vulkan-types.h | 15 +- spa/plugins/vulkan/vulkan-utils.c | 241 +++++++++++---------- spa/plugins/vulkan/vulkan-utils.h | 7 +- 10 files changed, 276 insertions(+), 274 deletions(-) create mode 100644 spa/plugins/vulkan/utils.c create mode 100644 spa/plugins/vulkan/utils.h diff --git a/spa/plugins/vulkan/meson.build b/spa/plugins/vulkan/meson.build index 62dc32123..d7e53de15 100644 --- a/spa/plugins/vulkan/meson.build +++ b/spa/plugins/vulkan/meson.build @@ -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') diff --git a/spa/plugins/vulkan/utils.c b/spa/plugins/vulkan/utils.c new file mode 100644 index 000000000..2ccd2a719 --- /dev/null +++ b/spa/plugins/vulkan/utils.c @@ -0,0 +1,91 @@ +/* Spa */ +/* SPDX-FileCopyrightText: Copyright © 2023 columbarius */ +/* SPDX-License-Identifier: MIT */ + +#include "utils.h" + +#include +#include +#include + +// 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]); +} diff --git a/spa/plugins/vulkan/utils.h b/spa/plugins/vulkan/utils.h new file mode 100644 index 000000000..9716804a3 --- /dev/null +++ b/spa/plugins/vulkan/utils.h @@ -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); diff --git a/spa/plugins/vulkan/vulkan-compute-filter.c b/spa/plugins/vulkan/vulkan-compute-filter.c index 50b78f460..cc9e2fcab 100644 --- a/spa/plugins/vulkan/vulkan-compute-filter.c +++ b/spa/plugins/vulkan/vulkan-compute-filter.c @@ -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 diff --git a/spa/plugins/vulkan/vulkan-compute-source.c b/spa/plugins/vulkan/vulkan-compute-source.c index 798c5f01a..95531f9c6 100644 --- a/spa/plugins/vulkan/vulkan-compute-source.c +++ b/spa/plugins/vulkan/vulkan-compute-source.c @@ -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 diff --git a/spa/plugins/vulkan/vulkan-compute-utils.c b/spa/plugins/vulkan/vulkan-compute-utils.c index 9ce89bc45..bdd81aeee 100644 --- a/spa/plugins/vulkan/vulkan-compute-utils.c +++ b/spa/plugins/vulkan/vulkan-compute-utils.c @@ -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); } diff --git a/spa/plugins/vulkan/vulkan-compute-utils.h b/spa/plugins/vulkan/vulkan-compute-utils.h index 46e80455c..4e1ea1cf8 100644 --- a/spa/plugins/vulkan/vulkan-compute-utils.h +++ b/spa/plugins/vulkan/vulkan-compute-utils.h @@ -7,6 +7,7 @@ #include #include #include +#include #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); diff --git a/spa/plugins/vulkan/vulkan-types.h b/spa/plugins/vulkan/vulkan-types.h index f28618774..5ca6b7b47 100644 --- a/spa/plugins/vulkan/vulkan-types.h +++ b/spa/plugins/vulkan/vulkan-types.h @@ -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; diff --git a/spa/plugins/vulkan/vulkan-utils.c b/spa/plugins/vulkan/vulkan-utils.c index e3850bb1f..5321b7ae9 100644 --- a/spa/plugins/vulkan/vulkan-utils.c +++ b/spa/plugins/vulkan/vulkan-utils.c @@ -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; diff --git a/spa/plugins/vulkan/vulkan-utils.h b/spa/plugins/vulkan/vulkan-utils.h index 4e393b195..45bbd12b2 100644 --- a/spa/plugins/vulkan/vulkan-utils.h +++ b/spa/plugins/vulkan/vulkan-utils.h @@ -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);