From dfe9601119730f8605fa3ff07ee7a365bd5eaa0f Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Wed, 9 Jul 2025 14:40:09 +0200 Subject: [PATCH] allocator: workaround linear blitting (#174) so nvidia as main gpu cant create linear modifiers and will give us a null bo if forced to linear, meanwhile without linear modifiers blitting fallbacks to cpu copying that is slow. so force linear mods, try create bo and if all else fails try again without. this way intel/amd as main and nvidia as dgpu will create linears and if nvidia is main it will be using cpu copying and still work but a bit slow. hide all of this behind AQ_FORCE_LINEAR_BLIT env var. since its a bit hackish. --- src/allocator/GBM.cpp | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/allocator/GBM.cpp b/src/allocator/GBM.cpp index ac64939..e06703b 100644 --- a/src/allocator/GBM.cpp +++ b/src/allocator/GBM.cpp @@ -140,7 +140,9 @@ Aquamarine::CGBMBuffer::CGBMBuffer(const SAllocatorBufferParams& params, Hypruti return; } - if (MULTIGPU) { + static const auto forceLinearBlit = envEnabled("AQ_FORCE_LINEAR_BLIT"); + auto const oldMods = explicitModifiers; // used in FORCE_LINEAR_BLIT case. + if (MULTIGPU && !forceLinearBlit) { // Try to use the linear format if available for cross-GPU compatibility. // However, Nvidia doesn't support linear, so this is a best-effort basis. for (auto const& f : FORMATS) { @@ -150,6 +152,14 @@ Aquamarine::CGBMBuffer::CGBMBuffer(const SAllocatorBufferParams& params, Hypruti break; } } + } else if (MULTIGPU && forceLinearBlit) { + // FIXME: Nvidia cannot render to linear buffers. What do? + // it seems it can import them, but not create? or is it nvidia <-> nvidia thats the trouble? + // without this blitting on laptops intel/amd <-> nvidia makes eglCreateImageKHR error and + // fallback to slow cpu copying. + + allocator->backend->log(AQ_LOG_DEBUG, "GBM: Buffer is marked as multigpu, forcing linear"); + explicitModifiers = {DRM_FORMAT_MOD_LINEAR}; } uint32_t flags = GBM_BO_USE_RENDERING; @@ -190,6 +200,23 @@ Aquamarine::CGBMBuffer::CGBMBuffer(const SAllocatorBufferParams& params, Hypruti } } + if (MULTIGPU && forceLinearBlit) { + // FIXME: most likely nvidia main gpu on multigpu + if (!bo) { + if (oldMods.empty()) + bo = gbm_bo_create(allocator->gbmDevice, attrs.size.x, attrs.size.y, attrs.format, GBM_BO_USE_RENDERING); + else + bo = gbm_bo_create_with_modifiers(allocator->gbmDevice, attrs.size.x, attrs.size.y, attrs.format, oldMods.data(), oldMods.size()); + + if (!bo) { + allocator->backend->log(AQ_LOG_ERROR, "GBM: Failed to allocate a GBM buffer: bo null"); + return; + } + + modifier = gbm_bo_get_modifier(bo); + } + } + if (!bo) { allocator->backend->log(AQ_LOG_ERROR, "GBM: Failed to allocate a GBM buffer: bo null"); return;