diff --git a/app/src/main/cpp/vkbridge/server_emu.c b/app/src/main/cpp/vkbridge/server_emu.c index 027019fec..072ed8a9d 100644 --- a/app/src/main/cpp/vkbridge/server_emu.c +++ b/app/src/main/cpp/vkbridge/server_emu.c @@ -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) diff --git a/app/src/main/cpp/vkbridge/server_emu.h b/app/src/main/cpp/vkbridge/server_emu.h index 252ca24cb..ed079692e 100644 --- a/app/src/main/cpp/vkbridge/server_emu.h +++ b/app/src/main/cpp/vkbridge/server_emu.h @@ -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 diff --git a/tools/vkbridge/client/emu.c b/tools/vkbridge/client/emu.c index 4a57eaa97..08918f280 100644 --- a/tools/vkbridge/client/emu.c +++ b/tools/vkbridge/client/emu.c @@ -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; diff --git a/tools/vkbridge/common/vkb_proto.h b/tools/vkbridge/common/vkb_proto.h index f8958785e..0291fe12c 100644 --- a/tools/vkbridge/common/vkb_proto.h +++ b/tools/vkbridge/common/vkb_proto.h @@ -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 { diff --git a/tools/vkbridge/host/mali_env.sh b/tools/vkbridge/host/mali_env.sh index f73d857bb..bb68a34fa 100755 --- a/tools/vkbridge/host/mali_env.sh +++ b/tools/vkbridge/host/mali_env.sh @@ -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"