Repository: godotengine/godot (language: cpp)

Issue:
Creating render pipeline for a `RDShaderFile` that doesn't have vertex shader causes crash
### Tested versions

4.4.rc3

### System information

Godot v4.4.rc.mono - EndeavourOS  SMP PREEMPT_DYNAMIC Sat, 22 Feb 2025 00:37:05 +0000 on Wayland - X11 display driver, Multi-window, 1 monitor - Vulkan (Mobile) - integrated AMD Radeon Graphics (RADV RENOIR) - AMD Ryzen 7 4800U with Radeon Graphics (16 threads)

### Issue description

If a glsl file only has `#[fragment]` but no `#[vertex]`, it can be successfully compiled and loaded in script. And if it is used in `RenderingDevice.render_pipeline_create`, the game will crash (if it's a tool script, the whole editor will crash).

### Steps to reproduce

Run the MRP, then the game crashes:
```
Stop reason: signal SIGSEGV: address not mapped to object (fault address: 0x0)
Stop reason: signal SIGSEGV: invalid permissions for mapped object (fault address: 0x7fffa7e21fd0)
```
Call stack:
```
___lldb_unnamed_symbol2415 (@___lldb_unnamed_symbol2415:686)
___lldb_unnamed_symbol2417 (@___lldb_unnamed_symbol2417:62)
___lldb_unnamed_symbol2420 (@___lldb_unnamed_symbol2420:108)
RenderingDeviceDriverVulkan::render_pipeline_create(RenderingDeviceDriver::ShaderID, RenderingDeviceDriver::VertexFormatID, RenderingDeviceCommons::RenderPrimitive, RenderingDeviceCommons::PipelineRasterizationState, RenderingDeviceCommons::PipelineMultisampleState, RenderingDeviceCommons::PipelineDepthStencilState, RenderingDeviceCommons::PipelineColorBlendState, VectorView<int>, BitField<RenderingDeviceCommons::PipelineDynamicStateFlags>, RenderingDeviceDriver::RenderPassID, unsigned int, VectorView<RenderingDeviceCommons::PipelineSpecializationConstant>) (/home/luo/godot/drivers/vulkan/rendering_device_driver_vulkan.cpp:5246)
RenderingDevice::render_pipeline_create(RID, long, long, RenderingDeviceCommons::RenderPrimitive, RenderingDeviceCommons::PipelineRasterizationState const&, RenderingDeviceCommons::PipelineMultisampleState const&, RenderingDeviceCommons::PipelineDepthStencilState const&, RenderingDeviceCommons::PipelineColorBlendState const&, BitField<RenderingDeviceCommons::PipelineDynamicStateFlags>, unsigned int, Vector<RenderingDeviceCommons::PipelineSpecializationConstant> const&) (/home/luo/godot/servers/rendering/rendering_device.cpp:3957)
RenderingDevice::_render_pipeline_create(RID, long, long, RenderingDeviceCommons::RenderPrimitive, Ref<RDPipelineRasterizationState> const&, Ref<RDPipelineMultisampleState> const&, Ref<RDPipelineDepthStencilState> const&, Ref<RDPipelineColorBlendState> const&, BitField<RenderingDeviceCommons::PipelineDynamicStateFlags>, unsigned int, TypedArray<RDPipelineSpecializationConstant> const&) (/home/luo/godot/servers/rendering/rendering_device.cpp:8269)
void call_with_variant_args_ret_helper<__UnexistingClass, RID, RID, long, long, RenderingDeviceCommons::RenderPrimitive, Ref<RDPipelineRasterizationState> const&, Ref<RDPipelineMultisampleState> const&, Ref<RDPipelineDepthStencilState> const&, Ref<RDPipelineColorBlendState> const&, BitField<RenderingDeviceCommons::PipelineDynamicStateFlags>, unsigned int, TypedArray<RDPipelineSpecializationConstant> const&, 0ul, 1ul, 2ul, 3ul, 4ul, 5ul, 6ul, 7ul, 8ul, 9ul, 10ul>(__UnexistingClass*, RID (__UnexistingClass::*)(RID, long, long, RenderingDeviceCommons::RenderPrimitive, Ref<RDPipelineRasterizationState> const&, Ref<RDPipelineMultisampleState> const&, Ref<RDPipelineDepthStencilState> const&, Ref<RDPipelineColorBlendState> const&, BitField<RenderingDeviceCommons::PipelineDynamicStateFlags>, unsigned int, TypedArray<RDPipelineSpecializationConstant> const&), Variant const**, Variant&, Callable::CallError&, IndexSequence<0ul, 1ul, 2ul, 3ul, 4ul, 5ul, 6ul, 7ul, 8ul, 9ul, 10ul>) (/home/luo/godot/core/variant/binder_common.h:767)
void call_with_variant_args_ret_dv<__UnexistingClass, RID, RID, long, long, RenderingDeviceCommons::RenderPrimitive, Ref<RDPipelineRasterizationState> const&, Ref<RDPipelineMultisampleState> const&, Ref<RDPipelineDepthStencilState> const&, Ref<RDPipelineColorBlendState> const&, BitField<RenderingDeviceCommons::PipelineDynamicStateFlags>, unsigned int, TypedArray<RDPipelineSpecializationConstant> const&>(__UnexistingClass*, RID (__UnexistingClass::*)(RID, long, long, RenderingDeviceCommons::RenderPrimitive, Ref<RDPipelineRasterizationState> const&, Ref<RDPipelineMultisampleState> const&, Ref<RDPipelineDepthStencilState> const&, Ref<RDPipelineColorBlendState> const&, BitField<RenderingDeviceCommons::PipelineDynamicStateFlags>, unsigned int, TypedArray<RDPipelineSpecializationConstant> const&), Variant const**, int, Variant&, Callable::CallError&, Vector<Variant> const&) (/home/luo/godot/core/variant/binder_common.h:546)
MethodBindTR<RID, RID, long, long, RenderingDeviceCommons::RenderPrimitive, Ref<RDPipelineRasterizationState> const&, Ref<RDPipelineMultisampleState> const&, Ref<RDPipelineDepthStencilState> const&, Ref<RDPipelineColorBlendState> const&, BitField<RenderingDeviceCommons::PipelineDynamicStateFlags>, unsigned int, TypedArray<RDPipelineSpecializationConstant> const&>::call(Object*, Variant const**, int, Callable::CallError&) const (/home/luo/godot/core/object/method_bind.h:524)
GDScriptFunction::call(GDScriptInstance*, Variant const**, int, Callable::CallError&, GDScriptFunction::CallState*) (/home/luo/godot/modules/gdscript/gdscript_vm.cpp:2013)
GDScriptInstance::callp(StringName const&, Variant const**, int, Callable::CallError&) (/home/luo/godot/modules/gdscript/gdscript.cpp:2053)
Node::_gdvirtual__ready_call() (/home/luo/godot/scene/main/node.h:391)
Node::_notification(int) (/home/luo/godot/scene/main/node.cpp:227)
Node::_notificationv(int, bool) (/home/luo/godot/scene/main/node.h:49)
CanvasItem::_notificationv(int, bool) (/home/luo/godot/scene/main/canvas_item.h:44)
Node2D::_notificationv(int, bool) (/home/luo/godot/scene/2d/node_2d.h:37)
Object::notification(int, bool) (/home/luo/godot/core/object/object.cpp:911)
Node::_propagate_ready() (/home/luo/godot/scene/main/node.cpp:282)
Node::_propagate_ready() (/home/luo/godot/scene/main/node.cpp:273)
Node::_set_tree(SceneTree*) (/home/luo/godot/scene/main/node.cpp:3289)
```

### Minimal reproduction project (MRP)

[RDShaderFileCrash.zip](https://github.com/user-attachments/files/19043836/RDShaderFileCrash.zip)


Discussion / hints:
Can't confirm on Windows 11, so might be platform specific

Can you test previous versions like 4.3 to check if this occurs there as well or if it is specific to 4.4?
The same with 4.3. 
Moreover, if there is only a vertex shader but no fragment shader, it reports errors at runtime, but not crash.

Fix patch:
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index 9a3e4fd9d7fa..638b529676a0 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -3850,6 +3850,9 @@ RID RenderingDevice::render_pipeline_create(RID p_shader, FramebufferFormatID p_
 	ERR_FAIL_NULL_V(shader, RID());
 	ERR_FAIL_COND_V_MSG(shader->is_compute, RID(), "Compute shaders can't be used in render pipelines");
 
+	// Validate pre-raster shader. One of stages must be vertex shader or mesh shader (not implemented yet).
+	ERR_FAIL_COND_V_MSG(!shader->stage_bits.has_flag(RDD::PIPELINE_STAGE_VERTEX_SHADER_BIT), RID(), "Pre-raster shader (vertex shader) is not provided for pipeline creation.");
+
 	FramebufferFormat fb_format;
 	{
 		_THREAD_SAFE_METHOD_


Test patch: