Non-Adreno round 5: gamescope memory fallback, Venus destroy guard, OpenAL depot

- gamescope 0131: DEVICE_LOCAL|HOST_VISIBLE requests fall back to host-visible
  memory (the bridge's unified-memory model lists none with both), with the
  request, type bits and memory types logged on failure; 0130's probe pipeline
  is kept and skipped when forced.
- Venus: GAMESCOPE_NO_YCBCR_SAMPLERS=1 from the start; virglrenderer ignores
  the destroy of a pipeline it never created instead of marking the context
  fatal (vtest server exit 137 on a Mali-G615).
- Steam's OpenAL depot (229020) maps to oalinst_dll, so games that list it
  (Hotline Miami) get OpenAL in their prefix.
This commit is contained in:
The412Banner committed 2026-10-13 10:44:02 -04:00
1 parent 8397965df2
commit 6199a93f52
7 files changed
+125

No files matched your search

@@ -21,6 +21,8 @@ object SteamRedists {
"228988" to ("vcredist2019_dll" to "VC++ 2019"),
"228989" to ("vcredist2022_dll" to "VC++ 2022"),
"228990" to ("d3dx9" to "DirectX (June 2010)"),
// OpenAL 2.0.7.0 (Hotline Miami lists it; without it HotlineGL.exe fails to load, c0000135).
"229020" to ("oalinst_dll" to "OpenAL"),
)
private val BLOCK = Regex("\"SharedDepots\"\\s*\\{([^}]*)\\}", RegexOption.IGNORE_CASE)
private val ENTRY = Regex("\"(\\d+)\"\\s+\"\\d+\"")
@@ -94,6 +94,10 @@ class VenusComponent(private val logFile: File?) : SessionPart() {
// layer stands in for. The session script checks it and falls back to llvmpipe.
"DROIDDECK_MALI_COMPAT=1",
"BL_VENUS=1",
// gamescope's composite layout without immutable YCbCr samplers from the start
// (patch 0130): a Mali-G615 refused every composite pipeline with them, and testing
// that through Venus took the render server down.
"GAMESCOPE_NO_YCBCR_SAMPLERS=1",
)
}
@@ -60,6 +60,8 @@ class WinCompSourcesTest {
@Test fun steamworksSharedDepotsMapToComponents() {
assertEquals(listOf("vcredist2015_dll" to "VC++ 2015", "d3dx9" to "DirectX (June 2010)"), WinCompSources.steamDepots(listOf("228986", "228990", "999")))
// Hotline Miami's OpenAL depot: the DLL-copy entry, which installs without running anything.
assertEquals(listOf("oalinst_dll" to "OpenAL"), WinCompSources.steamDepots(listOf("229020")))
}
// ---- per source ----
+7
View File
@@ -85,3 +85,10 @@ app's Wayland-hosted gamescope never reaches, or need a newer gamescope than the
refused every composite shader (blit, blur, RCAS: SPIR-V capabilities Shader, Sampled1D,
ImageQuery, no Float16) while EASU, NIS and the NV12 converter, which share the layout but never
touch binding 4, compiled.
- `0131-memory-type-fallback-keep-probe.patch`: `findMemoryType` asked for DEVICE_LOCAL|HOST_VISIBLE
memory falls back to host-visible memory without DEVICE_LOCAL, and a failure logs the requested
properties, the type bits and every memory type. The Mali bridge models a unified-memory GPU like a
discrete one (host-visible types without DEVICE_LOCAL), so the upload buffer found nothing and the
backend failed. Also: 0130's probe pipeline is kept instead of destroyed, and skipped when
`GAMESCOPE_NO_YCBCR_SAMPLERS=1` (destroying a pipeline the Venus host had refused killed the
render server).
@@ -0,0 +1,55 @@
diff --git a/src/rendervulkan.cpp b/src/rendervulkan.cpp
index d344a99..e699c85 100644
--- a/src/rendervulkan.cpp
+++ b/src/rendervulkan.cpp
@@ -331,7 +331,10 @@ bool CVulkanDevice::BInit(VkInstance instance, VkSurfaceKHR surface)
if ( !createLayouts() )
return false;
}
- VkPipeline probe = compilePipeline( 1, 0, SHADER_TYPE_BLIT, 1, 0, 0, 0, false );
+ // Forced off: no probe. Through Venus a pipeline the host refused can still come back as a
+ // handle, and destroying it later is a command the render server rejects - it killed the
+ // whole vtest context (Mali-G615: "vkDestroyPipeline resulted in CS error", exit 137).
+ VkPipeline probe = m_bYcbcrImmutableSamplers ? compilePipeline( 1, 0, SHADER_TYPE_BLIT, 1, 0, 0, 0, false ) : VK_NULL_HANDLE;
if ( probe == VK_NULL_HANDLE && m_bYcbcrImmutableSamplers )
{
vk_log.errorf( "composite pipeline refused; retrying without immutable YCbCr samplers" );
@@ -343,8 +346,8 @@ bool CVulkanDevice::BInit(VkInstance instance, VkSurfaceKHR surface)
probe = compilePipeline( 1, 0, SHADER_TYPE_BLIT, 1, 0, 0, 0, false );
vk_log.infof( "composite pipeline without immutable YCbCr samplers: %s", probe ? "accepted" : "STILL refused" );
}
- if ( probe != VK_NULL_HANDLE )
- vk.DestroyPipeline( device(), probe, nullptr );
+ // The probe is kept, never destroyed (see above): one pipeline.
+ (void)probe;
}
if (!createScratchResources())
return false;
@@ -1380,7 +1383,26 @@ int32_t CVulkanDevice::findMemoryType( VkMemoryPropertyFlags properties, uint32_
return i;
}
-
+
+ // A device that lists its host-visible memory without DEVICE_LOCAL (the Mali bridge models a
+ // unified-memory GPU that way, as a discrete one would) still has it all on the GPU: settle for
+ // host-visible memory rather than fail ("findMemoryType failed", then no backend).
+ if ( properties & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT && properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT )
+ {
+ int32_t nFallback = findMemoryType( properties & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, requiredTypeBits );
+ static bool s_bLogged = false;
+ if ( !s_bLogged )
+ {
+ s_bLogged = true;
+ vk_log.infof( "no memory type with properties 0x%x in type bits 0x%x; without DEVICE_LOCAL: %d", properties, requiredTypeBits, nFallback );
+ }
+ if ( nFallback >= 0 )
+ return nFallback;
+ }
+
+ vk_log.errorf( "findMemoryType: no memory type with properties 0x%x in type bits 0x%x (%u types)", properties, requiredTypeBits, m_memoryProperties.memoryTypeCount );
+ for ( uint32_t i = 0; i < m_memoryProperties.memoryTypeCount; i++ )
+ vk_log.errorf( " memory type %u: flags 0x%x heap %u", i, m_memoryProperties.memoryTypes[ i ].propertyFlags, m_memoryProperties.memoryTypes[ i ].heapIndex );
return -1;
}
+1
View File
@@ -78,6 +78,7 @@ git clone -q --depth 1 -b 1.5.10 https://github.com/anholt/libepoxy.git
git clone -q --depth 1 -b v1.4.365 https://github.com/KhronosGroup/Vulkan-Headers.git
git clone -q --depth 1 -b virglrenderer-1.3.0 https://gitlab.freedesktop.org/virgl/virglrenderer.git
git -C virglrenderer apply "$REPO/tools/venus/virglrenderer-android.patch"
git -C virglrenderer apply "$REPO/tools/venus/virglrenderer-destroy-unknown-pipeline.patch"
cat > compat/log/log.h <<'EOC'
#pragma once
#include <android/log.h>
@@ -0,0 +1,54 @@
diff --git a/src/venus/venus-protocol/vn_protocol_renderer_pipeline.h b/src/venus/venus-protocol/vn_protocol_renderer_pipeline.h
index ce82e59..8798de9 100644
--- a/src/venus/venus-protocol/vn_protocol_renderer_pipeline.h
+++ b/src/venus/venus-protocol/vn_protocol_renderer_pipeline.h
@@ -3290,7 +3290,11 @@ static inline void vn_encode_vkCreateComputePipelines_reply(struct vn_cs_encoder
static inline void vn_decode_vkDestroyPipeline_args_temp(struct vn_cs_decoder *dec, struct vn_command_vkDestroyPipeline *args)
{
vn_decode_VkDevice_lookup(dec, &args->device);
- vn_decode_VkPipeline_lookup(dec, &args->pipeline);
+ {
+ uint64_t id;
+ vn_decode_uint64_t(dec, &id);
+ args->pipeline = (VkPipeline)(uintptr_t)vkr_cs_decoder_lookup_object_for_destroy((const struct vkr_cs_decoder *)dec, id, VK_OBJECT_TYPE_PIPELINE);
+ }
if (vn_decode_simple_pointer(dec)) {
vn_cs_decoder_set_fatal(dec);
} else {
diff --git a/src/venus/vkr_cs.h b/src/venus/vkr_cs.h
index c72c5cc..b45061f 100644
--- a/src/venus/vkr_cs.h
+++ b/src/venus/vkr_cs.h
@@ -324,6 +324,32 @@ vkr_cs_decoder_lookup_object(const struct vkr_cs_decoder *dec,
return obj;
}
+/* For a destroy command only: an id the renderer never created (the driver refused the create,
+ * which the guest may not have waited for) is logged and destroyed as VK_NULL_HANDLE, a no-op,
+ * instead of marking the whole context fatal - that took the vtest server down (exit 137) when
+ * gamescope destroyed a compute pipeline a Mali-G615 had refused. */
+static inline struct vkr_object *
+vkr_cs_decoder_lookup_object_for_destroy(const struct vkr_cs_decoder *dec,
+ vkr_object_id id,
+ VkObjectType type)
+{
+ struct vkr_object *obj;
+
+ if (!id)
+ return NULL;
+
+ mtx_lock(dec->object_mutex);
+ const struct hash_entry *entry =
+ _mesa_hash_table_search((struct hash_table *)dec->object_table, &id);
+ obj = likely(entry) ? entry->data : NULL;
+ mtx_unlock(dec->object_mutex);
+ if (unlikely(!obj || obj->type != type)) {
+ vkr_log("destroy of unknown object %" PRIu64 " of type %d ignored", id, type);
+ return NULL;
+ }
+ return obj;
+}
+
static inline void
vkr_cs_decoder_reset_temp_pool(struct vkr_cs_decoder *dec)
{