diff --git a/spa/plugins/vulkan/meson.build b/spa/plugins/vulkan/meson.build index d7e53de15..86f5eac7f 100644 --- a/spa/plugins/vulkan/meson.build +++ b/spa/plugins/vulkan/meson.build @@ -1,5 +1,6 @@ spa_vulkan_sources = [ 'plugin.c', + 'pixel-formats.c', 'vulkan-compute-filter.c', 'vulkan-compute-source.c', 'vulkan-compute-utils.c', diff --git a/spa/plugins/vulkan/pixel-formats.c b/spa/plugins/vulkan/pixel-formats.c new file mode 100644 index 000000000..06144d758 --- /dev/null +++ b/spa/plugins/vulkan/pixel-formats.c @@ -0,0 +1,33 @@ +/* Spa */ +/* SPDX-FileCopyrightText: Copyright © 2023 columbarius */ +/* SPDX-License-Identifier: MIT */ + +#include "pixel-formats.h" + +#include +#include + +struct pixel_info { + uint32_t format; + uint32_t bpp; +} pixel_infos[] = { + { SPA_VIDEO_FORMAT_RGBA_F32, 16 }, + { SPA_VIDEO_FORMAT_BGRA, 4 }, + { SPA_VIDEO_FORMAT_RGBA, 4 }, + { SPA_VIDEO_FORMAT_BGRx, 4 }, + { SPA_VIDEO_FORMAT_RGBx, 4 }, + { SPA_VIDEO_FORMAT_BGR, 3 }, + { SPA_VIDEO_FORMAT_RGB, 3 }, +}; + +bool get_pixel_format_info(uint32_t format, struct pixel_format_info *info) +{ + struct pixel_info *p; + SPA_FOR_EACH_ELEMENT(pixel_infos, p) { + if (p->format != format) + continue; + info->bpp = p->bpp; + return true; + } + return false; +} diff --git a/spa/plugins/vulkan/pixel-formats.h b/spa/plugins/vulkan/pixel-formats.h new file mode 100644 index 000000000..949733107 --- /dev/null +++ b/spa/plugins/vulkan/pixel-formats.h @@ -0,0 +1,12 @@ +/* Spa */ +/* SPDX-FileCopyrightText: Copyright © 2023 columbarius */ +/* SPDX-License-Identifier: MIT */ + +#include +#include + +struct pixel_format_info { + uint32_t bpp; // bytes per pixel +}; + +bool get_pixel_format_info(uint32_t format, struct pixel_format_info *info); diff --git a/spa/plugins/vulkan/vulkan-compute-utils.c b/spa/plugins/vulkan/vulkan-compute-utils.c index bdd81aeee..336384b98 100644 --- a/spa/plugins/vulkan/vulkan-compute-utils.c +++ b/spa/plugins/vulkan/vulkan-compute-utils.c @@ -28,6 +28,7 @@ #include "vulkan-compute-utils.h" #include "vulkan-utils.h" #include "utils.h" +#include "pixel-formats.h" #define VULKAN_INSTANCE_FUNCTION(name) \ PFN_##name name = (PFN_##name)vkGetInstanceProcAddr(s->base.instance, #name) @@ -247,13 +248,16 @@ static int runExportSHMBuffers(struct vulkan_compute_state *s) { if (p->direction == SPA_DIRECTION_INPUT) continue; + struct pixel_format_info pixel_info; + CHECK(get_pixel_format_info(p->format, &pixel_info)); + if (p->spa_buffers[p->current_buffer_id]->datas[0].type == SPA_DATA_MemPtr) { struct spa_buffer *spa_buf = p->spa_buffers[p->current_buffer_id]; struct vulkan_read_pixels_info readInfo = { .data = spa_buf->datas[0].data, .offset = spa_buf->datas[0].chunk->offset, .stride = spa_buf->datas[0].chunk->stride, - .bytes_per_pixel = 16, + .bytes_per_pixel = pixel_info.bpp, .size.width = s->constants.width, .size.height = s->constants.height, }; @@ -479,6 +483,7 @@ int spa_vulkan_compute_use_buffers(struct vulkan_compute_state *s, struct vulkan vulkan_wait_idle(&s->base); clear_buffers(s, p); + p->format = SPA_VIDEO_FORMAT_UNKNOWN; bool alloc = flags & SPA_NODE_BUFFERS_FLAG_ALLOC; int ret; @@ -544,6 +549,7 @@ int spa_vulkan_compute_use_buffers(struct vulkan_compute_state *s, struct vulkan p->spa_buffers[i] = buffers[i]; p->n_buffers++; } + p->format = dsp_info->format; return 0; } diff --git a/spa/plugins/vulkan/vulkan-compute-utils.h b/spa/plugins/vulkan/vulkan-compute-utils.h index 4e1ea1cf8..39e7ba3bd 100644 --- a/spa/plugins/vulkan/vulkan-compute-utils.h +++ b/spa/plugins/vulkan/vulkan-compute-utils.h @@ -33,6 +33,8 @@ struct vulkan_stream { uint32_t busy_buffer_id; uint32_t ready_buffer_id; + uint32_t format; + struct vulkan_buffer buffers[MAX_BUFFERS]; struct spa_buffer *spa_buffers[MAX_BUFFERS]; uint32_t n_buffers; diff --git a/spa/plugins/vulkan/vulkan-utils.c b/spa/plugins/vulkan/vulkan-utils.c index 5321b7ae9..889af0bfa 100644 --- a/spa/plugins/vulkan/vulkan-utils.c +++ b/spa/plugins/vulkan/vulkan-utils.c @@ -248,13 +248,13 @@ int vulkan_read_pixels(struct vulkan_base *s, struct vulkan_read_pixels_info *in const char *d = (const char *)v + img_sub_layout.offset; unsigned char *p = (unsigned char *)info->data + info->offset; - uint32_t bytes_per_pixel = 16; uint32_t pack_stride = img_sub_layout.rowPitch; + spa_log_trace_fp(s->log, "Read pixels: %p to %p, stride: %d, width %d, height %d, offset %d, pack_stride %d", d, p, info->stride, info->size.width, info->size.height, info->offset, pack_stride); if (pack_stride == info->stride) { memcpy(p, d, info->stride * info->size.height); } else { for (uint32_t i = 0; i < info->size.height; i++) { - memcpy(p + i * info->stride, d + i * pack_stride, info->size.width * bytes_per_pixel); + memcpy(p + i * info->stride, d + i * pack_stride, info->size.width * info->bytes_per_pixel); } } vkUnmapMemory(s->device, vk_buf->memory);