summaryrefslogtreecommitdiff
path: root/src/render
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2025-11-30 14:32:51 -0500
committerAndrew Opalach <andrew@akon.city> 2025-11-30 14:32:51 -0500
commitc8412bbedae0fce38db96833732e8ce904721e4c (patch)
tree4611046186c714513d042966ce97825df0fecf9e /src/render
parent0d6d13425015d78606232874498327cabcb0e4e2 (diff)
downloadcamu-c8412bbedae0fce38db96833732e8ce904721e4c.tar.gz
camu-c8412bbedae0fce38db96833732e8ce904721e4c.tar.bz2
camu-c8412bbedae0fce38db96833732e8ce904721e4c.zip
Build cleanup and fixes from sink testing
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/render')
-rw-r--r--src/render/meson.build56
-rw-r--r--src/render/queue_libplacebo.c15
-rw-r--r--src/render/renderer.h5
-rw-r--r--src/render/renderer_libplacebo.c100
-rw-r--r--src/render/renderer_libplacebo.h2
-rw-r--r--src/render/renderer_momo.c3
6 files changed, 113 insertions, 68 deletions
diff --git a/src/render/meson.build b/src/render/meson.build
index 157cd63..a7ccb58 100644
--- a/src/render/meson.build
+++ b/src/render/meson.build
@@ -9,11 +9,9 @@ if get_option('renderer') == 'momo'
render_args += ['-DCAMU_RENDERER_MOMO']
elif get_option('renderer') == 'libplacebo'
libplacebo_found = false
- if 'libplacebo' not in get_option('force_fallback_for')
+ if 'libplacebo' not in get_option('force_fallback_for') and get_option('wrap_mode') != 'forcefallback'
libplacebo = dependency('libplacebo', required: false, allow_fallback: false)
- if libplacebo.found()
- libplacebo_found = true
- endif
+ libplacebo_found = libplacebo.found()
endif
if not libplacebo_found
libplacebo_opts = ['warning_level=2', 'demos=false', 'tests=false', 'bench=false', 'fuzz=false',
@@ -28,7 +26,7 @@ elif get_option('renderer') == 'libplacebo'
if get_option('renderer-api') == 'vulkan' or get_option('renderer-api') == 'dx11'
if get_option('renderer-compiler') == 'shaderc'
shaderc_found = false
- if 'shaderc' not in get_option('force_fallback_for')
+ if 'shaderc' not in get_option('force_fallback_for') and get_option('wrap_mode') != 'forcefallback'
if is_windows
shaderc = dependency('shaderc_combined', required: false, allow_fallback: false)
else
@@ -47,11 +45,14 @@ elif get_option('renderer') == 'libplacebo'
shaderc_opts.add_cmake_defines({ 'SHADERC_SKIP_TESTS': true })
shaderc_opts.add_cmake_defines({ 'SHADERC_SKIP_EXAMPLES': true })
shaderc_opts.add_cmake_defines({ 'SHADERC_SKIP_COPYRIGHT_CHECK': true })
+ # glslang
shaderc_opts.add_cmake_defines({ 'ENABLE_GLSLANG_BINARIES': false })
- shaderc_opts.add_cmake_defines({ 'ENABLE_SPVREMAPPER': false })
shaderc_opts.add_cmake_defines({ 'ENABLE_HLSL': false })
+ shaderc_opts.add_cmake_defines({ 'ENABLE_SPVREMAPPER': false })
+ shaderc_opts.add_cmake_defines({ 'ENABLE_EXCEPTIONS': false })
spirv_optimizer = true
shaderc_opts.add_cmake_defines({ 'ENABLE_OPT': spirv_optimizer })
+ # spirv-tools
shaderc_opts.add_cmake_defines({ 'ENABLE_EXCEPTIONS_ON_MSVC': false })
shaderc_proj = cmake.subproject('shaderc', options: shaderc_opts)
shaderc = shaderc_proj.dependency('shaderc')
@@ -66,9 +67,7 @@ elif get_option('renderer') == 'libplacebo'
shaderc_proj.dependency('SPIRV-Tools-static')
]
if spirv_optimizer
- render_deps += [
- shaderc_proj.dependency('SPIRV-Tools-opt'),
- ]
+ render_deps += [shaderc_proj.dependency('SPIRV-Tools-opt')]
endif
endif
libplacebo_opts += ['shaderc=enabled', 'glslang=disabled']
@@ -77,19 +76,36 @@ elif get_option('renderer') == 'libplacebo'
if glslang.found()
render_deps += [glslang]
else
+ # Currently does not build.
+ prefer_static = get_option('prefer_static')
+ spirv_optimizer = false
+ if spirv_optimizer
+ spirv_headers_proj = cmake.subproject('SPIRV-Headers')
+ spirv_headers = spirv_headers_proj.dependency('SPIRV-Headers')
+ spirv_tools_opts = cmake.subproject_options()
+ spirv_tools_opts.add_cmake_defines({ 'SPIRV-Headers_SOURCE_DIR': meson.source_root() + '/subprojects/SPIRV-Headers-b824a46' })
+ spirv_tools_opts.add_cmake_defines({ 'ENABLE_EXCEPTIONS_ON_MSVC': false })
+ spirv_tools_proj = cmake.subproject('SPIRV-Tools', options: spirv_tools_opts)
+ spirv_tools = spirv_tools_proj.dependency('SPIRV-Tools-static')
+ spirv_tools_opt = spirv_tools_proj.dependency('SPIRV-Tools-opt')
+ endif
glslang_opts = cmake.subproject_options()
glslang_opts.set_override_option('warning_level', '0')
reltype = is_minsize ? 'MinSizeRel' : 'Release'
glslang_opts.add_cmake_defines({ 'CMAKE_BUILD_TYPE': is_debug ? 'Debug' : reltype })
- spirv_optimizer = false
+ glslang_opts.add_cmake_defines({ 'ENABLE_GLSLANG_BINARIES': false })
+ glslang_opts.add_cmake_defines({ 'ENABLE_HLSL': false })
+ glslang_opts.add_cmake_defines({ 'ENABLE_SPVREMAPPER': false })
+ glslang_opts.add_cmake_defines({ 'ENABLE_EXCEPTIONS': false })
glslang_opts.add_cmake_defines({ 'ENABLE_OPT': spirv_optimizer })
+ glslang_opts.add_cmake_defines({ 'ALLOW_EXTERNAL_SPIRV_TOOLS': spirv_optimizer })
glslang_proj = cmake.subproject('glslang', options: glslang_opts)
spirv = glslang_proj.dependency('SPIRV')
glslang = glslang_proj.dependency('glslang')
glslang_default_resource_limits = glslang_proj.dependency('glslang-default-resource-limits')
- meson.override_dependency('SPIRV', spirv)
- meson.override_dependency('glslang', glslang)
- meson.override_dependency('glslang-default-resource-limits', glslang_default_resource_limits)
+ meson.override_dependency('SPIRV', spirv, static: prefer_static)
+ meson.override_dependency('glslang', glslang, static: prefer_static)
+ meson.override_dependency('glslang-default-resource-limits', glslang_default_resource_limits, static: prefer_static)
render_deps += [
glslang_proj.dependency('MachineIndependent'),
glslang_proj.dependency('OSDependent'),
@@ -98,6 +114,13 @@ elif get_option('renderer') == 'libplacebo'
glslang,
glslang_default_resource_limits
]
+ if spirv_optimizer
+ render_deps += [
+ spirv_tools,
+ spirv_headers,
+ spirv_tools_opt
+ ]
+ endif
endif
libplacebo_opts += ['glslang=enabled', 'shaderc=disabled']
endif
@@ -140,11 +163,9 @@ endif
if get_option('subtitles').enabled()
libass_found = false
- if 'libass' not in get_option('force_fallback_for')
+ if 'libass' not in get_option('force_fallback_for') and get_option('wrap_mode') != 'forcefallback'
libass = dependency('libass', required: false, allow_fallback: false)
- if libass.found()
- libass_found = true
- endif
+ libass_found = libass.found()
endif
if not libass_found
libass_opts = ['test=disabled']
@@ -191,6 +212,7 @@ if get_option('subtitles').enabled()
'gobject=disabled',
'cairo=disabled',
'chafa=disabled',
+ 'icu=disabled',
'freetype=disabled',
# This does not override yield, and yielding breaks the build if tests=enabled.
# https://github.com/mesonbuild/meson/issues/5214
diff --git a/src/render/queue_libplacebo.c b/src/render/queue_libplacebo.c
index c78562c..e3540c3 100644
--- a/src/render/queue_libplacebo.c
+++ b/src/render/queue_libplacebo.c
@@ -164,12 +164,12 @@ static struct camu_overlay *first_nonref_overlay(struct camu_frame_queue_lp *lq,
static struct camu_overlay *create_subtitle_overlay(struct camu_overlay *prev, pl_gpu gpu, ASS_Image *ass_frame)
{
- u32 frame_count = 1;
+ u16 frame_count = 1;
ASS_Image *head_ass_frame = ass_frame;
- while (ass_frame->next) { frame_count++; ass_frame = ass_frame->next; }
+ while (ass_frame->next) { al_assert(frame_count < UINT16_MAX); frame_count++; ass_frame = ass_frame->next; }
ass_frame = head_ass_frame;
- u32 prev_alloc = prev ? prev->alloc : 0;
+ u16 prev_alloc = prev ? prev->alloc : 0;
struct camu_overlay *overlay = camu_overlay_alloc(prev, frame_count,
sizeof(struct pl_overlay) + sizeof(struct pl_overlay_part));
if (frame_count > prev_alloc) {
@@ -225,9 +225,9 @@ static struct camu_overlay *create_subtitle_overlay(struct camu_overlay *prev, p
};
u32 c = ass_frame->color;
current_part->color[0] = (c >> 24) / 255.0;
- current_part->color[1] = ((c >> 16) & 0xFF) / 255.0;
- current_part->color[2] = ((c >> 8) & 0xFF) / 255.0;
- current_part->color[3] = 1.0 - (c & 0xFF) / 255.0;
+ current_part->color[1] = ((c >> 16) & 0xff) / 255.0;
+ current_part->color[2] = ((c >> 8) & 0xff) / 255.0;
+ current_part->color[3] = 1.0 - (c & 0xff) / 255.0;
current->parts = current_part;
current->num_parts = 1;
@@ -317,8 +317,9 @@ static bool map_av_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *
if (overlay) {
overlay->ref++;
out_frame->overlays = CAMU_OVERLAY_OFFSET(overlay, 0);
- out_frame->num_overlays = overlay->num;
((struct pl_source_frame *)src)->frame_data = overlay;
+ } else {
+ out_frame->overlays = NULL;
}
}
nn_mutex_unlock(&lq->subtitle_lock);
diff --git a/src/render/renderer.h b/src/render/renderer.h
index 3331baa..0eae5cb 100644
--- a/src/render/renderer.h
+++ b/src/render/renderer.h
@@ -30,12 +30,13 @@ enum {
struct camu_overlay {
u16 ref;
- u32 alloc;
+ u16 alloc;
s32 num;
struct nn_mutex *lock;
};
#define CAMU_OVERLAY_OFFSET(overlay, n) ((void *)(((u8 *)(overlay)) + sizeof(struct camu_overlay) + (n)))
+#define CAMU_OVERLAY_FROM_HEAD(p) (struct camu_overlay *)(((u8 *)p) - sizeof(struct camu_overlay))
struct camu_frame_queue;
struct camu_codec_stream;
@@ -67,7 +68,7 @@ struct camu_renderer {
u32 (*get_latency)(struct camu_renderer *);
void (*resize)(struct camu_renderer *, u32 *, u32 *);
void (*set)(struct camu_renderer *, u8, u8);
- void (*render)(struct camu_renderer *, struct camu_screen *, bool);
+ bool (*render)(struct camu_renderer *, struct camu_screen *, bool);
#ifdef CAMU_HAVE_FFMPEG
s32 (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, s32 flags);
void *opaque;
diff --git a/src/render/renderer_libplacebo.c b/src/render/renderer_libplacebo.c
index 3b69c64..01aa764 100644
--- a/src/render/renderer_libplacebo.c
+++ b/src/render/renderer_libplacebo.c
@@ -13,7 +13,8 @@
#include "queue_libplacebo.h"
#ifdef AL_DEBUG
-#define RENDERER_DEBUG 1
+// vkQueueSubmit2: VK_ERROR_VALIDATION_FAILED_EXT leads to an annoying deadlock.
+#define RENDERER_DEBUG 0
#else
#define RENDERER_DEBUG 0
#endif
@@ -37,8 +38,11 @@ static void renderer_lp_resize(struct camu_renderer *renderer, u32 *width, u32 *
struct camu_renderer_lp *lr = (struct camu_renderer_lp *)renderer;
if (lr->swapchain) {
if (lr->have_frame) {
- pl_swapchain_submit_frame(lr->swapchain);
- lr->have_frame = false;
+ if (pl_swapchain_submit_frame(lr->swapchain)) {
+ lr->have_frame = false;
+ } else {
+ log_error("Failed to submit frame on resize.");
+ }
}
pl_swapchain_resize_compat(lr->swapchain, width, height);
}
@@ -365,7 +369,9 @@ static inline intptr_t float_64_hash(f64 value)
return hash;
}
-static void renderer_lp_render(struct camu_renderer *renderer, struct camu_screen *scr, bool force)
+
+
+static bool renderer_lp_render(struct camu_renderer *renderer, struct camu_screen *scr, bool force)
{
struct camu_renderer_lp *lr = (struct camu_renderer_lp *)renderer;
@@ -377,15 +383,14 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree
if (!lr->have_frame) {
struct pl_swapchain_frame frame;
- if (!pl_swapchain_start_frame(lr->swapchain, &frame)) {
- if (force) {
- pl_swapchain_swap_buffers(lr->swapchain);
- }
- return;
+ if (pl_swapchain_start_frame(lr->swapchain, &frame)) {
+ pl_frame_from_swapchain(&lr->target, &frame);
+ pl_frame_clear_rgba(lr->gpu, &lr->target, clear_color);
+ lr->have_frame = true;
+ } else {
+ log_error("Failed to start frame, fatal.");
+ return false;
}
- pl_frame_from_swapchain(&lr->target, &frame);
- pl_frame_clear_rgba(lr->gpu, &lr->target, clear_color);
- lr->have_frame = true;
}
f64 mouse_x, mouse_y;
@@ -405,11 +410,14 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree
lr->params.hooks[0]->parameters[1].data->f = (f32)mouse_y;
}
+ enum {
+ RESULT_SUBMIT = 1,
+ RESULT_SUBMIT_AND_WAIT = 1 << 1
+ };
+
+ u8 result = 0;
struct pl_frame *target = &lr->target;
struct pl_frame_mix mix;
-
- bool do_gpu_finish = false;
-
struct camu_screen_video *video;
while (scr->videos.count > 0) {
bool any_eof = false;
@@ -419,7 +427,7 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree
// If mix.frames is NULL, read() returned QUEUE_MORE.
if (mix.frames) {
// weighted is only set when read() returns QUEUE_OK.
- do_gpu_finish |= weighted;
+ result |= (1 | 1 << weighted);
// Terrible hack. Lets us distinguish single frames with the same dimensions.
// Tied to a libplacebo patch to consider info_priv in the hash.
intptr_t hash = (intptr_t)video->buf;
@@ -431,15 +439,22 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree
hash += float_64_hash(video->view.fov);
lr->params.hooks[0]->parameters[2].data->f = (f32)video->view.fov;
}
- lr->params.info_priv = (void *)hash;
- target->crop = mix.frames[0]->crop;
- if (!scr->subtitles_enabled) {
- // This basically discards the subtitles of each frame before it's rendered.
- // So, toggling the subtitles of a single frame (paused) won't work.
- for (s32 j = 0; j < mix.num_frames; j++) {
- ((struct pl_frame *)mix.frames[j])->num_overlays = 0;
+#ifdef CAMU_HAVE_SUBTITLES
+ for (u32 j = 0; j < (u32)mix.num_frames; j++) {
+ struct pl_frame *mix_frame = (struct pl_frame *)mix.frames[j];
+ if (!mix_frame->overlays) continue;
+ struct camu_overlay *overlay = CAMU_OVERLAY_FROM_HEAD(mix_frame->overlays);
+ if (!overlay->num) continue;
+ if (scr->subtitles_enabled) {
+ mix_frame->num_overlays = overlay->num;
+ hash += overlay->num;
+ } else {
+ mix_frame->num_overlays = 0;
}
}
+#endif
+ lr->params.info_priv = (void *)hash;
+ target->crop = mix.frames[0]->crop;
target->crop.x1 *= video->view.zoom / video->view.stretch;
target->crop.y1 *= video->view.zoom * video->view.stretch;
target->crop.x0 += video->view.x_offset;
@@ -447,7 +462,14 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree
target->crop.x1 += video->view.x_offset;
target->crop.y1 += video->view.y_offset;
target->rotation = video->view.rotation;
- //lr->params.color_adjustment = pl_color_adjustment(.saturation = 0.0);
+ /*
+ //lr->params.color_map_params = pl_color_map_params(.inverse_tone_mapping = true);
+ if () {
+ target->color = pl_color_space_srgb;
+ target->color.hdr.max_luma = PL_COLOR_SDR_WHITE - 50.f;
+ target->color.hdr.min_luma = (PL_COLOR_SDR_WHITE - 50.f) / PL_COLOR_SDR_CONTRAST;
+ }
+ */
pl_render_image_mix(lr->renderer, &mix, target, &lr->params);
}
} else {
@@ -468,32 +490,30 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree
lr->params.hooks = NULL;
lr->params.num_hooks = 0;
- if (!scr->videos.count && !force) {
- // Don't spin too hard on a potential error state.
+ // Considerations about the result of the loop above.
+ // 1. Any given call to video_buffer_read() may not produce a frame.
+ // 2. If a buffer signals EOF, by the time run_queue() happens at the bottom of the loop all
+ // previous buffers could have been queued for removal. Meaning, at this point, videos.count
+ // would be 0 while there could be data we want to display rendered to the frame.
+ if (!(result & RESULT_SUBMIT) && !force) {
nn_thread_sleep(NNWT_TS_FROM_USEC(192));
- return;
+ return true;
}
- if (!pl_swapchain_submit_frame(lr->swapchain)) {
+ if (pl_swapchain_submit_frame(lr->swapchain)) {
+ lr->have_frame = false;
+ } else {
log_error("Failed to submit frame, possibly fatal.");
+ return false;
}
- lr->have_frame = false;
pl_swapchain_swap_buffers(lr->swapchain);
- if (do_gpu_finish) {
- // Block until render completes.
+ if (result & RESULT_SUBMIT_AND_WAIT) {
pl_gpu_finish(lr->gpu);
}
-#if 0
- f64 tick = nn_get_tick();
- f64 frame_time = tick - lr->last_render_tick;
- if (frame_time > (1.0 / 24.0)) { // 24fps is totally arbitrary.
- log_info("FRAME_TIME: %fs (%.2ffps)", frame_time, 1.0 / frame_time);
- }
- lr->last_render_tick = tick;
-#endif
+ return true;
}
void renderer_lp_free(struct camu_renderer **renderer)
@@ -521,7 +541,7 @@ void renderer_lp_free(struct camu_renderer **renderer)
*renderer = NULL;
}
-struct camu_renderer *camu_renderer_lp_create(void)
+struct camu_renderer *camu_renderer_libplacebo_create(void)
{
struct camu_renderer_lp *lr = al_alloc_object(struct camu_renderer_lp);
lr->r.create_renderer = renderer_lp_create_renderer;
diff --git a/src/render/renderer_libplacebo.h b/src/render/renderer_libplacebo.h
index 5d5cf9b..727e0b3 100644
--- a/src/render/renderer_libplacebo.h
+++ b/src/render/renderer_libplacebo.h
@@ -42,4 +42,4 @@ struct camu_renderer_lp {
#endif
};
-struct camu_renderer *camu_renderer_lp_create(void);
+struct camu_renderer *camu_renderer_libplacebo_create(void);
diff --git a/src/render/renderer_momo.c b/src/render/renderer_momo.c
index 3a0e7ed..02ccaee 100644
--- a/src/render/renderer_momo.c
+++ b/src/render/renderer_momo.c
@@ -85,12 +85,13 @@ static u32 renderer_momo_get_latency(struct camu_renderer *renderer)
return 0;
}
-static void renderer_momo_render(struct camu_renderer *renderer, struct camu_screen *scr, bool force)
+static bool renderer_momo_render(struct camu_renderer *renderer, struct camu_screen *scr, bool force)
{
struct camu_renderer_momo *mr = (struct camu_renderer_momo *)renderer;
(void)scr;
(void)force;
MOMO_Render(&mr->mmr);
+ return true;
}
static void renderer_momo_free(struct camu_renderer **renderer)