allocator: workaround linear blitting

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.
This commit is contained in:
Tom Englund 2025-05-23 08:35:27 +02:00
parent d04e01e70c
commit aa21963d37

View file

@ -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;