feat(vkbridge): report VK_EXT_robustness2 on drivers without it (Mali r44)

DXVK refuses to start without robustness2. GameNative's wrapper reports it on
Mali r44 (robustBufferAccess2, robustImageAccess2, nullDescriptor) without
enforcing it, and DXVK games run. Same here, as VKB_EMU_ROBUSTNESS2: the
client advertises the extension and features, the server strips the feature
struct and keeps robustBufferAccess on (VKBRIDGE_EMU_ROBUSTNESS2=0 disables).
The host Mali imitation now hides robustness2 too; DXVK checker 10/10.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1U9H1evGNjHRQ3wRUdv5V
This commit is contained in:
Ahmad Sayed Alsayed EbrahimandClaude Opus 5.5 committed 2026-10-10 17:05:04 +03:00
1 parent 0f078c439a
commit ce34349ffb
5 files changed
+31 -5

No files matched your search

+14 -1
View File
@@ -33,13 +33,14 @@ uint32_t vkb_emu_detect(const vkb_dispatch *idt, VkPhysicalDevice pd, uint32_t *
idt->vkEnumerateDeviceExtensionProperties(pd, NULL, &n, NULL);
VkExtensionProperties *e = calloc(n ? n : 1, sizeof(*e));
idt->vkEnumerateDeviceExtensionProperties(pd, NULL, &n, e);
int divisor = 0, depth_clip = 0, maint5 = 0;
int divisor = 0, depth_clip = 0, maint5 = 0, robust2 = 0;
for (uint32_t i = 0; i < n; i++) {
if (!strcmp(e[i].extensionName, "VK_EXT_vertex_attribute_divisor") ||
!strcmp(e[i].extensionName, "VK_KHR_vertex_attribute_divisor"))
divisor = 1;
if (!strcmp(e[i].extensionName, "VK_EXT_depth_clip_enable")) depth_clip = 1;
if (!strcmp(e[i].extensionName, "VK_KHR_maintenance5")) maint5 = 1;
if (!strcmp(e[i].extensionName, "VK_EXT_robustness2") || !strcmp(e[i].extensionName, "VK_KHR_robustness2")) robust2 = 1;
}
free(e);
/* VKBRIDGE_FAKE_MISSING=bc,divisor,clip,cull,depthclip pretends the GPU lacks them (host tests). */
@@ -51,6 +52,7 @@ uint32_t vkb_emu_detect(const vkb_dispatch *idt, VkPhysicalDevice pd, uint32_t *
if (token(fake, "cull")) f.shaderCullDistance = VK_FALSE;
if (token(fake, "depthclip")) depth_clip = 0;
if (token(fake, "maint5")) maint5 = 0;
if (token(fake, "robustness2")) robust2 = 0;
}
uint32_t emu = 0;
VkPhysicalDeviceProperties props;
@@ -63,6 +65,10 @@ uint32_t vkb_emu_detect(const vkb_dispatch *idt, VkPhysicalDevice pd, uint32_t *
if (!f.shaderClipDistance && !env_off("VKBRIDGE_EMU_CLIP")) emu |= VKB_EMU_CLIP_DISTANCE;
if (!f.shaderCullDistance && !env_off("VKBRIDGE_EMU_CULL")) emu |= VKB_EMU_CULL_DISTANCE;
if (!depth_clip && f.depthClamp && !env_off("VKBRIDGE_EMU_DEPTHCLIP")) emu |= VKB_EMU_DEPTH_CLIP;
/* DXVK will not start without robustness2. Mali r44 lacks it; GameNative's wrapper reports it
* (robustBufferAccess2, robustImageAccess2, nullDescriptor) without enforcing it, and DXVK
* games run - out-of-bounds reads and null descriptors are then up to the driver. */
if (!robust2 && f.robustBufferAccess && !env_off("VKBRIDGE_EMU_ROBUSTNESS2")) emu |= VKB_EMU_ROBUSTNESS2;
/* PointSize in geometry/tessellation stages: stripped when the feature is missing. */
if (!f.shaderTessellationAndGeometryPointSize && (f.geometryShader || f.tessellationShader)) emu |= VKB_EMU_POINT_SIZE;
uint32_t miss = 0;
@@ -72,6 +78,7 @@ uint32_t vkb_emu_detect(const vkb_dispatch *idt, VkPhysicalDevice pd, uint32_t *
if (!f.shaderCullDistance) miss |= VKB_EMU_CULL_DISTANCE;
if (!depth_clip) miss |= VKB_EMU_DEPTH_CLIP;
if (emu & VKB_EMU_MAINT5) miss |= VKB_EMU_MAINT5;
if (!robust2) miss |= VKB_EMU_ROBUSTNESS2;
*missing = miss;
return emu & VKB_EMU_IMPLEMENTED;
}
@@ -119,6 +126,12 @@ void vkb_emu_device_create_info(vkb_srv_table *inst, VkPhysicalDevice pd, uint32
if (emu & VKB_EMU_DIVISOR) chain_remove(ci, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT);
if (emu & VKB_EMU_DEPTH_CLIP) chain_remove(ci, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT);
if (emu & VKB_EMU_MAINT5) chain_remove(ci, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES);
if (emu & VKB_EMU_ROBUSTNESS2) {
chain_remove(ci, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT);
/* What robustness the GPU has stays on; robustBufferAccess2 asks for at least that. */
VkPhysicalDeviceFeatures *rf = find_features(ci);
if (rf) rf->robustBufferAccess = VK_TRUE;
}
}
void vkb_emu_device_init(vkb_srv_table *dev, uint32_t emu)
+1 -1
View File
@@ -6,7 +6,7 @@
/* Emulations that are implemented (the rest are never offered to the client). */
#define VKB_EMU_IMPLEMENTED (VKB_EMU_MAINT5 | VKB_EMU_CLIP_DISTANCE | VKB_EMU_CULL_DISTANCE | VKB_EMU_POINT_SIZE | VKB_EMU_BCN | \
VKB_EMU_DIVISOR | VKB_EMU_DEPTH_CLIP)
VKB_EMU_DIVISOR | VKB_EMU_DEPTH_CLIP | VKB_EMU_ROBUSTNESS2)
#define VKB_EMU_BUCKETS 1024
+12
View File
@@ -23,6 +23,7 @@ const VkExtensionProperties *vkb_emu_extensions(vkb_physdev *pd, uint32_t *n)
list[c++] = (VkExtensionProperties){"VK_KHR_vertex_attribute_divisor", 1};
}
if (EMU(pd, VKB_EMU_DEPTH_CLIP)) list[c++] = (VkExtensionProperties){"VK_EXT_depth_clip_enable", 1};
if (EMU(pd, VKB_EMU_ROBUSTNESS2)) list[c++] = (VkExtensionProperties){"VK_EXT_robustness2", 1};
*n = c;
return list;
}
@@ -35,6 +36,11 @@ void vkb_emu_patch_limits(vkb_physdev *pd, VkPhysicalDeviceProperties *p)
void vkb_emu_patch_properties_chain(vkb_physdev *pd, VkBaseOutStructure *b)
{
if (EMU(pd, VKB_EMU_ROBUSTNESS2) && b->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT) {
VkPhysicalDeviceRobustness2PropertiesEXT *r = (void *)b;
r->robustStorageBufferAccessSizeAlignment = 4;
r->robustUniformBufferAccessSizeAlignment = 256;
}
if (EMU(pd, VKB_EMU_DIVISOR)) {
if (b->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT)
((VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *)b)->maxVertexAttribDivisor = UINT32_MAX;
@@ -79,6 +85,12 @@ void vkb_emu_patch_features_chain(vkb_physdev *pd, VkBaseOutStructure *b)
if (EMU(pd, VKB_EMU_DEPTH_CLIP)) d3->extendedDynamicState3DepthClampEnable = VK_FALSE;
}
break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT:
if (EMU(pd, VKB_EMU_ROBUSTNESS2)) {
VkPhysicalDeviceRobustness2FeaturesEXT *r = (void *)b;
r->robustBufferAccess2 = r->robustImageAccess2 = r->nullDescriptor = VK_TRUE;
}
break;
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT:
set_feature(pd, VKB_EMU_DEPTH_CLIP, &((VkPhysicalDeviceDepthClipEnableFeaturesEXT *)b)->depthClipEnable);
break;
+1
View File
@@ -37,6 +37,7 @@ static inline const char *vkb_mem_strategy_name(uint32_t s)
#define VKB_EMU_POINT_SIZE (1u << 4) /* strip PointSize from geometry/tessellation stages */
#define VKB_EMU_DEPTH_CLIP (1u << 5) /* VK_EXT_depth_clip_enable via depthClamp */
#define VKB_EMU_MAINT5 (1u << 6) /* VK_KHR_maintenance5 on a driver without it */
#define VKB_EMU_ROBUSTNESS2 (1u << 7) /* VK_EXT_robustness2 reported, not enforced (GameNative's r44 profile) */
/* vkbQueryServer reply (per physical device). */
typedef struct vkb_server_pd_info {
+3 -3
View File
@@ -1,15 +1,15 @@
#!/bin/bash
# Source this: a host bridge server that behaves like the Mali-G720 driver as far as Phase 0
# found (no BCn, clip/cull distance, vertex attribute divisor, maintenance5, push descriptors; Vulkan 1.3).
# found (no BCn, clip/cull distance, vertex attribute divisor, maintenance5, push descriptors, robustness2; Vulkan 1.3).
_vkb_host=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
export VKBRIDGE_SOCKET=${XDG_RUNTIME_DIR:-/tmp}/vkbridge-host.sock
pgrep -x vkbridge-server >/dev/null && kill $(pgrep -x vkbridge-server) 2>/dev/null; sleep 0.3
rm -f "$VKBRIDGE_SOCKET"
VKBRIDGE_FAKE_MISSING=${VKB_MISSING:-bc,clip,cull,divisor,maint5,depthclip,push} VK_DRIVER_FILES=${VKB_HOST_ICD:-/usr/share/vulkan/icd.d/radeon_icd.json} \
VKBRIDGE_FAKE_MISSING=${VKB_MISSING:-bc,clip,cull,divisor,maint5,depthclip,push,robustness2} VK_DRIVER_FILES=${VKB_HOST_ICD:-/usr/share/vulkan/icd.d/radeon_icd.json} \
nohup "$_vkb_host/out/vkbridge-server" --socket "$VKBRIDGE_SOCKET" --log "$_vkb_host/out/server.log" >/dev/null 2>&1 &
for _i in $(seq 50); do [ -S "$VKBRIDGE_SOCKET" ] && break; sleep 0.1; done
chmod 666 "$VKBRIDGE_SOCKET"
export VK_DRIVER_FILES=$_vkb_host/out/vkbridge_icd.json
export VKBRIDGE_HIDE_EXTS=VK_KHR_maintenance5,VK_KHR_push_descriptor,VK_EXT_vertex_attribute_divisor,VK_KHR_vertex_attribute_divisor,VK_EXT_depth_clip_enable
export VKBRIDGE_HIDE_EXTS=VK_KHR_maintenance5,VK_KHR_push_descriptor,VK_EXT_robustness2,VK_KHR_robustness2,VK_EXT_vertex_attribute_divisor,VK_KHR_vertex_attribute_divisor,VK_EXT_depth_clip_enable
export VKBRIDGE_MAX_API=1.3
echo "vkbridge server up, imitating Mali's gaps"