vulkan: move format enumeration into utils functions

This commit is contained in:
columbarius 2023-09-23 14:32:46 +02:00
parent 6646a04439
commit 50c4fa43d6
10 changed files with 264 additions and 272 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,88 @@
/* 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)
@ -543,6 +544,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)
{
@ -655,22 +667,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,11 @@ struct vulkan_format_info {
struct vulkan_modifier_info *infos;
};
struct vulkan_format_infos {
uint32_t formatCount;
struct vulkan_format_info *infos;
};
struct vulkan_buffer {
int fd;
VkImage image;
@ -35,11 +40,6 @@ struct vulkan_buffer {
struct vulkan_base_info {
uint32_t queueFlags;
struct {
uint32_t formatCount;
uint32_t *formats;
} formatInfo;
};
struct vulkan_base {
@ -53,9 +53,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++) {
@ -867,13 +760,127 @@ 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;
for (uint32_t 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);
}
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;
}
@ -883,7 +890,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

@ -86,8 +86,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);
@ -99,5 +99,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);