Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iOS Metal driver crash with error in shader_compile_binary_from_spirv #103334

Closed
migueldeicaza opened this issue Feb 26, 2025 · 2 comments · Fixed by #103337
Closed

iOS Metal driver crash with error in shader_compile_binary_from_spirv #103334

migueldeicaza opened this issue Feb 26, 2025 · 2 comments · Fixed by #103337

Comments

@migueldeicaza
Copy link
Contributor

migueldeicaza commented Feb 26, 2025

Tested versions

Godot 4.4/RC2

System information

iOS 18.3, iPad M2

Issue description

I was testing the new sample "Museum of all Things" on iOS, and ended up with a crash, I do not think the actual crash location is important, (but I included it), I think the root problem is with the SPIRV compiler.

ERROR: FATAL: Index p_index = 17 is out of bounds (size() = 0).
at: get (./core/templates/cowdata.h:219)
* 
* thread #1, name = 'Godot Main Thread [instance #1]', queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=1, subcode=0x1283a5ed4)
  * frame #0: 0x00000001283a5ed4 Xogot.debug.dylib`CowData<RID>::get(this=0x000000014eac4278, p_index=17) const at cowdata.h:219:3
    frame #1: 0x00000001283a5e04 Xogot.debug.dylib`Vector<RID>::operator[](this=0x000000014eac4270, p_index=17) const at vector.h:102:75
    frame #2: 0x000000012f905970 Xogot.debug.dylib`ShaderRD::version_get_shader(this=0x000000014e45a958, p_version=(_id = 52677773885443), p_variant=17) at shader_rd.h:193:10
    frame #3: 0x000000012fb395b8 Xogot.debug.dylib`RendererSceneRenderImplementation::SceneShaderForwardClustered::ShaderData::_get_shader_variant(this=0x00000001562ecc10, p_shader_version=17) const at scene_shader_forward_clustered.cpp:412:74
    frame #4: 0x000000012fb39680 Xogot.debug.dylib`RendererSceneRenderImplementation::SceneShaderForwardClustered::ShaderData::get_vertex_input_mask(this=0x00000001562ecc10, p_pipeline_version=PIPELINE_VERSION_COLOR_PASS, p_color_pass_flags=0, p_ubershader=true) at scene_shader_forward_clustered.cpp:433:20
    frame #5: 0x000000012fafe390 Xogot.debug.dylib`RendererSceneRenderImplementation::RenderForwardClustered::_mesh_compile_pipeline_for_surface(this=0x000000014e458010, p_shader=0x00000001562ecc10, p_mesh_surface=0x0000000168e1f110, p_ubershader=true, p_instanced_surface=false, p_source=PIPELINE_SOURCE_SURFACE, r_pipeline_key=0x000000016b5d8b28, r_pipeline_pairs=0x0000000000000000) at render_forward_clustered.cpp:4445:34
    frame #6: 0x000000012fafecf0 Xogot.debug.dylib`RendererSceneRenderImplementation::RenderForwardClustered::_mesh_compile_pipelines_for_surface(this=0x000000014e458010, p_surface=0x000000016b5d8be0, p_global=0x000000014e45b8cc, p_source=PIPELINE_SOURCE_SURFACE, r_pipeline_pairs=0x0000000000000000) at render_forward_clustered.cpp:4501:5
    frame #7: 0x000000012fb00400 Xogot.debug.dylib`RendererSceneRenderImplementation::RenderForwardClustered::_mesh_generate_all_pipelines_for_surface_cache(this=0x000000014e458010, p_surface_cache=0x000000012233c5a8, p_global=0x000000014e45b8cc) at render_forward_clustered.cpp:4617:2
    frame #8: 0x000000012faf1990 Xogot.debug.dylib`RendererSceneRenderImplementation::RenderForwardClustered::_update_dirty_geometry_pipelines(this=0x000000014e458010) at render_forward_clustered.cpp:4634:4
    frame #9: 0x000000012fae3934 Xogot.debug.dylib`RendererSceneRenderImplementation::RenderForwardClustered::_update_dirty_geometry_instances(this=0x000000014e458010) at render_forward_clustered.cpp:4625:2
    frame #10: 0x000000012fae22c8 Xogot.debug.dylib`RendererSceneRenderImplementation::RenderForwardClustered::_fill_render_list(this=0x000000014e458010, p_render_list=RENDER_LIST_OPAQUE, p_render_data=0x000000016b5db608, p_pass_mode=PASS_MODE_COLOR, p_using_sdfgi=false, p_using_opaque_gi=false, p_using_motion_pass=false, p_append=false) at render_forward_clustered.cpp:917:2
    frame #11: 0x000000012faebaf0 Xogot.debug.dylib`RendererSceneRenderImplementation::RenderForwardClustered::_render_scene(this=0x000000014e458010, p_render_data=0x000000016b5db608, p_default_bg_color=0x000000016b5db470) at render_forward_clustered.cpp:1870:2
    frame #12: 0x000000012f97b3ec Xogot.debug.dylib`RendererSceneRenderRD::render_scene(this=0x000000014e458010, p_render_buffers=0x000000016e54d3f8, p_camera_data=0x000000016b5dcc28, p_prev_camera_data=0x000000016e54d410, p_instances=0x00000001066546d0, p_lights=0x0000000106654730, p_reflection_probes=0x0000000106654790, p_voxel_gi_instances=0x00000001066547f0, p_decals=0x00000001066547c0, p_lightmaps=0x0000000106654760, p_fog_volumes=0x0000000106654850, p_environment=(_id = 219709052026883), p_camera_attributes=(_id = 0), p_compositor=(_id = 0), p_shadow_atlas=(_id = 196962905227866), p_occluder_debug_tex=(_id = 0), p_reflection_atlas=(_id = 4230542786560), p_reflection_probe=(_id = 0), p_reflection_probe_pass=-1, p_screen_mesh_lod_threshold=0.000418760465, p_render_shadows=0x0000000106655490, p_render_shadow_count=4, p_render_sdfgi_regions=0x000000010665d498, p_render_sdfgi_region_count=0, p_sdfgi_update_data=0x000000010665d9d8, r_render_info=0x000000016e54d650) at renderer_scene_render_rd.cpp:1260:2
    frame #13: 0x000000012f521e94 Xogot.debug.dylib`RendererSceneCull::_render_scene(this=0x0000000106654010, p_camera_data=0x000000016b5dcc28, p_render_buffers=0x000000016e54d3f8, p_environment=(_id = 219709052026883), p_force_camera_attributes=(_id = 0), p_compositor=(_id = 0), p_visible_layers=252706815, p_scenario=(_id = 4221952851968), p_viewport=(_id = 196941430391384), p_shadow_atlas=(_id = 196962905227866), p_reflection_probe=(_id = 0), p_reflection_probe_pass=-1, p_screen_mesh_lod_threshold=0.000418760465, p_using_shadows=true, r_render_info=0x000000016e54d650) at renderer_scene_cull.cpp:3557:16
    frame #14: 0x000000012f51fb2c Xogot.debug.dylib`RendererSceneCull::render_camera(this=0x0000000106654010, p_render_buffers=0x000000016e54d3f8, p_camera=(_id = 197005854900225), p_scenario=(_id = 4221952851968), p_viewport=(_id = 196941430391384), p_viewport_size=Size2 @ 0x000000016b5dcde8, p_jitter_phase_count=0, p_screen_mesh_lod_threshold=0.000418760465, p_shadow_atlas=(_id = 196962905227866), p_xr_interface=0x000000016b5dcfd8, r_render_info=0x000000016e54d650) at renderer_scene_cull.cpp:2778:2
    frame #15: 0x000000012f56ec6c Xogot.debug.dylib`RendererViewport::_draw_3d(this=0x0000000303b91910, p_viewport=0x000000016e54d390) at renderer_viewport.cpp:296:31
    frame #16: 0x000000012f56f2e4 Xogot.debug.dylib`RendererViewport::_draw_viewport(this=0x0000000303b91910, p_viewport=0x000000016e54d390) at renderer_viewport.cpp:363:3
    frame #17: 0x000000012f572664 Xogot.debug.dylib`RendererViewport::draw_viewports(this=0x0000000303b91910, p_swap_buffers=true) at renderer_viewport.cpp:870:4
    frame #18: 0x000000012f74a7ec Xogot.debug.dylib`RenderingServerDefault::_draw(this=0x000000011dcdf110, p_swap_buffers=true, frame_step=1.250828666666667) at rendering_server_default.cpp:86:34
    frame #19: 0x000000012f74cdf4 Xogot.debug.dylib`RenderingServerDefault::draw(this=0x000000011dcdf110, p_present=true, frame_step=1.250828666666667) at rendering_server_default.cpp:436:3
    frame #20: 0x00000001270eb9e4 Xogot.debug.dylib`Main::iteration() at main.cpp:4537:39
    frame #21: 0x000000012a7c03e0 Xogot.debug.dylib`ProgressDialog::_update_ui(this=0x0000000154a68010) at progress_dialog.cpp:151:3
    frame #22: 0x000000012a7c09b0 Xogot.debug.dylib`ProgressDialog::add_task(this=0x0000000154a68010, p_task=0x000000016b5deb60, p_label=0x000000016b5deb58, p_steps=5, p_can_cancel=false) at progress_dialog.cpp:214:2
    frame #23: 0x000000012a14f698 Xogot.debug.dylib`EditorNode::progress_add_task(p_task=0x000000016b5deb60, p_label=0x000000016b5deb58, p_steps=5, p_can_cancel=false) at editor_node.cpp:5077:48
    frame #24: 0x000000012a14f4a4 Xogot.debug.dylib`EditorProgress::EditorProgress(this=0x000000016b5deb68, p_task=0x000000016b5deb60, p_label=0x000000016b5deb58, p_amount=5, p_can_cancel=false, p_force_background=false) at editor_node.cpp:192:3
    frame #25: 0x000000012a14f774 Xogot.debug.dylib`EditorProgress::EditorProgress(this=0x000000016b5deb68, p_task=0x000000016b5deb60, p_label=0x000000016b5deb58, p_amount=5, p_can_cancel=false, p_force_background=false) at editor_node.cpp:190:135
    frame #26: 0x0000000129f0bb24 Xogot.debug.dylib`EditorFileSystem::_first_scan_filesystem(this=0xffffffffffffffff) at editor_file_system.cpp:305:22
    frame #27: 0x0000000129f15ad0 Xogot.debug.dylib`EditorFileSystem::scan(this=0xffffffffffffffff) at editor_file_system.cpp:1067:3
    frame #28: 0x000000012a154b60 Xogot.debug.dylib`EditorNode::_notification(this=0x00000001523fce10, p_what=17) at editor_node.cpp:665:40
    frame #29: 0x000000012a198624 Xogot.debug.dylib`EditorNode::_notificationv(this=0x00000001523fce10, p_notification=17, p_reversed=false) at editor_node.h:124:2
    frame #30: 0x0000000130cfd500 Xogot.debug.dylib`Object::notification(this=0x00000001523fce10, p_notification=17, p_reversed=false) at object.cpp:914:3
    frame #31: 0x000000012cae70d0 Xogot.debug.dylib`SceneTree::_process_group(this=0xffffffffffffffff, p_group=0x00000001523f5520, p_physics=false) at scene_tree.cpp:1066:8
    frame #32: 0x000000012cae460c Xogot.debug.dylib`SceneTree::_process(this=0xffffffffffffffff, p_physics=false) at scene_tree.cpp:1143:8
    frame #33: 0x000000012cae50d4 Xogot.debug.dylib`SceneTree::process(this=0xffffffffffffffff, p_time=0.14917133333333318) at scene_tree.cpp:584:2
    frame #34: 0x00000001270eb868 Xogot.debug.dylib`Main::iteration() at main.cpp:4521:44
    frame #35: 0x0000000130c9a604 Xogot.debug.dylib`GodotInstance::iteration(this=0xffffffffffffffff) at godot_instance.cpp:112:9
    frame #36: 0x0000000127077ec0 Xogot.debug.dylib`void call_with_ptr_args_ret_helper<__UnexistingClass, bool>(p_instance=0x000000014c6b24d0, p_method=(Xogot.debug.dylib`GodotInstance::iteration() at godot_instance.cpp:110), p_args=0x0000000000000000, r_ret=0x000000016b5dfeff, (null)=IndexSequence<> @ 0x000000016b5dfcaf) at binder_common.h:346:22
    frame #37: 0x0000000127077e1c Xogot.debug.dylib`void call_with_ptr_args_ret<__UnexistingClass, bool>(p_instance=0x000000014c6b24d0, p_method=(Xogot.debug.dylib`GodotInstance::iteration() at godot_instance.cpp:110), p_args=0x0000000000000000, r_ret=0x000000016b5dfeff) at binder_common.h:594:2
    frame #38: 0x0000000127077788 Xogot.debug.dylib`MethodBindTR<bool>::ptrcall(this=0x000000030290b510, p_object=0xffffffffffffffff, p_args=0x0000000000000000, r_ret=0x000000016b5dfeff) const at method_bind.h:547:3
    frame #39: 0x0000000130c59ad4 Xogot.debug.dylib`gdextension_object_method_bind_ptrcall(p_method_bind=0x000000030290b510, p_instance=0x000000014c6b24d1, p_args=0x0000000000000000, p_ret=0x000000016b5dfeff) at gdextension_interface.cpp:1419:6
    frame #40: 0x000000010e74a3d0 SwiftGodot`GodotInstance.iteration() at GodotInstance.swift:76:12
    frame #41: 0x00000001258b9e88 Xogot.debug.dylib`closure #1 in GodotApp.iterate(, instance=0x0000000300620460) at GodotAppView.swift:641:34
    frame #42: 0x00000001254f0dbc Xogot.debug.dylib`closure #1 in closure #1 in GodotInstance.async(args=SwiftGodot.Arguments @ 0x000000016b5e0578, callback=0x00000001258f36cc Xogot.debug.dylib`partial apply forwarder for closure #1 () -> () in Xogot.GodotApp.iterate() -> () at <compiler-generated>) at SwiftGodotKit.swift:354:17
    frame #43: 0x000000010d7931e8 SwiftGodot`CallableWrapper.invoke(arguments=SwiftGodot.Arguments @ 0x000000016b5e0698, retPtr=0x16b5e0b70, err=0x16b5e091c) at Wrapped.swift:803:28
    frame #44: 0x000000010d793118 SwiftGodot`closure #1 in invokeWrappedCallable(arguments=SwiftGodot.Arguments @ 0x000000016b5e0728, wrapperPtr=0x30058eb00, retPtr=0x16b5e0b70, err=0x16b5e091c) at Wrapped.swift:789:14
    frame #45: 0x000000010d793360 SwiftGodot`thunk for @callee_guaranteed (@guaranteed Arguments) -> () at <compiler-generated>:0
    frame #46: 0x000000010d75ce20 SwiftGodot`withArguments<()>(pargs=nil, argc=0, body=0x10d793ef8) at Arguments.swift:384:18
    frame #47: 0x000000010d793060 SwiftGodot`invokeWrappedCallable(wrapperPtr=0x30058eb00, pargs=nil, argc=0, retPtr=0x16b5e0b70, err=0x16b5e091c) at Wrapped.swift:785:5
    frame #48: 0x000000010d79391c SwiftGodot`@objc invokeWrappedCallable(wrapperPtr:pargs:argc:retPtr:err:) at <compiler-generated>:0
    frame #49: 0x0000000130c5e454 Xogot.debug.dylib`CallableCustomExtension::call(this=0x00000003029f9110, p_arguments=0x0000000000000000, p_argcount=0, r_return_value=0x000000016b5e0b70, r_call_error=0x000000016b5e0b04) const at gdextension_interface.cpp:172:3
    frame #50: 0x000000013081e1b8 Xogot.debug.dylib`Callable::callp(this=0x000000030076cca8, p_arguments=0x0000000000000000, p_argcount=0, r_return_value=0x000000016b5e0b70, r_call_error=0x000000016b5e0b04) const at callable.cpp:57:11
    frame #51: 0x000000012961c4c0 Xogot.debug.dylib`InstanceState<CoreStringNames*>::InstanceState(this=0xd47754701bb0007b, (null)=0x000000016b5e0bf7) - 18446744068720311103

The SPIRV translator produces a lot of these error messages:

ERROR: Failed to compile stage Vertex: BaseInstance requires Metal 1.1 and Mac or Apple A9+ hardware.
at: shader_compile_binary_from_spirv (drivers/metal/rendering_device_driver_metal.mm:2106)
ERROR: Condition "shader_data.is_empty()" is true.
at: _compile_variant (servers/rendering/renderer_rd/shader_rd.cpp:345)

Googling the message indicates that some users are setting this value in advance, this was the patch that introduced it to the C API:

https://github.com/KhronosGroup/SPIRV-Cross/pull/1615/files

The following one-line patch fixes it, but I suspect Godot needs a better way of catching the scenario where a shader fails to compile and report that, rather than continuing:

https://gist.github.com/migueldeicaza/b73592b4e10118cdc1aff9cb2667cc81

At that point, detecting whether the device supports the feature might be worth doing, but for now, this value won't be any worse, and will at least not crash.

Steps to reproduce

Export this app for iOS:

https://github.com/m4ym4y/museum-of-all-things

Minimal reproduction project (MRP)

https://github.com/m4ym4y/museum-of-all-things

@akien-mga akien-mga added this to the 4.x milestone Feb 26, 2025
@akien-mga akien-mga changed the title 4.4/iOS/metal driver crash. iOS Metal driver crash with error in shader_compile_binary_from_spirv Feb 26, 2025
@akien-mga akien-mga moved this from Unassessed to Very Bad in 4.x Release Blockers Feb 26, 2025
@stuartcarnie
Copy link
Contributor

Fixed by #103337

@stuartcarnie
Copy link
Contributor

Thanks for finding this, @migueldeicaza – great catch! Also, thanks for sharing that Godot project - very cool!

At that point, detecting whether the device supports the feature might be worth doing, but for now, this value won't be any worse, and will at least not crash.

It is supported on all devices that Godot supports, so we're fine to blanket enable it – I'm surprised we haven't hit it before! I've run the Bistro demo on my iPhone and it didn't require this feature 🤯

@akien-mga akien-mga modified the milestones: 4.x, 4.4 Feb 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Very Bad
Development

Successfully merging a pull request may close this issue.

3 participants