Browse Source

Merge pull request #44950 from reduz/shader-debugger

Added ability to visualize native shaders
Rémi Verschelde 4 years ago
parent
commit
a7baf01352

+ 72 - 0
editor/editor_native_shader_source_visualizer.cpp

@@ -0,0 +1,72 @@
+/*************************************************************************/
+/*  editor_native_shader_source_visualizer.cpp                           */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#include "editor_native_shader_source_visualizer.h"
+
+#include "scene/gui/text_edit.h"
+
+void EditorNativeShaderSourceVisualizer::_inspect_shader(RID p_shader) {
+	if (versions) {
+		memdelete(versions);
+		versions = nullptr;
+	}
+
+	RS::ShaderNativeSourceCode nsc = RS::get_singleton()->shader_get_native_source_code(p_shader);
+
+	versions = memnew(TabContainer);
+	versions->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+	versions->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+	for (int i = 0; i < nsc.versions.size(); i++) {
+		TabContainer *vtab = memnew(TabContainer);
+		vtab->set_name("Version " + itos(i));
+		vtab->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+		vtab->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+		versions->add_child(vtab);
+		for (int j = 0; j < nsc.versions[i].stages.size(); j++) {
+			TextEdit *vtext = memnew(TextEdit);
+			vtext->set_readonly(true);
+			vtext->set_name(nsc.versions[i].stages[j].name);
+			vtext->set_text(nsc.versions[i].stages[j].code);
+			vtext->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+			vtext->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+			vtab->add_child(vtext);
+		}
+	}
+	add_child(versions);
+	popup_centered_ratio();
+}
+
+void EditorNativeShaderSourceVisualizer::_bind_methods() {
+	ClassDB::bind_method("_inspect_shader", &EditorNativeShaderSourceVisualizer::_inspect_shader);
+}
+EditorNativeShaderSourceVisualizer::EditorNativeShaderSourceVisualizer() {
+	add_to_group("_native_shader_source_visualizer");
+	set_title(TTR("Native Shader Source Inspector"));
+}

+ 50 - 0
editor/editor_native_shader_source_visualizer.h

@@ -0,0 +1,50 @@
+/*************************************************************************/
+/*  editor_native_shader_source_visualizer.h                             */
+/*************************************************************************/
+/*                       This file is part of:                           */
+/*                           GODOT ENGINE                                */
+/*                      https://godotengine.org                          */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md).   */
+/*                                                                       */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the       */
+/* "Software"), to deal in the Software without restriction, including   */
+/* without limitation the rights to use, copy, modify, merge, publish,   */
+/* distribute, sublicense, and/or sell copies of the Software, and to    */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions:                                             */
+/*                                                                       */
+/* The above copyright notice and this permission notice shall be        */
+/* included in all copies or substantial portions of the Software.       */
+/*                                                                       */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
+/*************************************************************************/
+
+#ifndef EDITOR_NATIVE_SHADER_SOURCE_VISUALIZER_H
+#define EDITOR_NATIVE_SHADER_SOURCE_VISUALIZER_H
+
+#include "scene/gui/dialogs.h"
+#include "scene/gui/tab_container.h"
+
+class EditorNativeShaderSourceVisualizer : public AcceptDialog {
+	GDCLASS(EditorNativeShaderSourceVisualizer, AcceptDialog)
+	TabContainer *versions = nullptr;
+
+	void _inspect_shader(RID p_shader);
+
+protected:
+	static void _bind_methods();
+
+public:
+	EditorNativeShaderSourceVisualizer();
+};
+
+#endif // EDITOR_NATIVE_SHADER_SOURCE_VISUALIZER_H

+ 3 - 0
editor/editor_node.cpp

@@ -6519,6 +6519,9 @@ EditorNode::EditorNode() {
 
 
 	center_split->connect("resized", callable_mp(this, &EditorNode::_vp_resized));
 	center_split->connect("resized", callable_mp(this, &EditorNode::_vp_resized));
 
 
+	native_shader_source_visualizer = memnew(EditorNativeShaderSourceVisualizer);
+	gui_base->add_child(native_shader_source_visualizer);
+
 	orphan_resources = memnew(OrphanResourcesDialog);
 	orphan_resources = memnew(OrphanResourcesDialog);
 	gui_base->add_child(orphan_resources);
 	gui_base->add_child(orphan_resources);
 
 

+ 3 - 0
editor/editor_node.h

@@ -34,6 +34,7 @@
 #include "editor/editor_data.h"
 #include "editor/editor_data.h"
 #include "editor/editor_export.h"
 #include "editor/editor_export.h"
 #include "editor/editor_folding.h"
 #include "editor/editor_folding.h"
+#include "editor/editor_native_shader_source_visualizer.h"
 #include "editor/editor_run.h"
 #include "editor/editor_run.h"
 #include "editor/inspector_dock.h"
 #include "editor/inspector_dock.h"
 #include "editor/property_editor.h"
 #include "editor/property_editor.h"
@@ -322,6 +323,8 @@ private:
 	String current_path;
 	String current_path;
 	MenuButton *update_spinner;
 	MenuButton *update_spinner;
 
 
+	EditorNativeShaderSourceVisualizer *native_shader_source_visualizer;
+
 	String defer_load_scene;
 	String defer_load_scene;
 	Node *_last_instanced_scene;
 	Node *_last_instanced_scene;
 
 

+ 1 - 1
scene/main/canvas_item.h

@@ -149,7 +149,7 @@ public:
 	static void finish_shaders();
 	static void finish_shaders();
 	static void flush_changes();
 	static void flush_changes();
 
 
-	RID get_shader_rid() const;
+	virtual RID get_shader_rid() const override;
 
 
 	virtual Shader::Mode get_shader_mode() const override;
 	virtual Shader::Mode get_shader_mode() const override;
 
 

+ 19 - 0
scene/resources/material.cpp

@@ -36,6 +36,7 @@
 #include "editor/editor_settings.h"
 #include "editor/editor_settings.h"
 #endif
 #endif
 
 
+#include "scene/main/scene_tree.h"
 #include "scene/scene_string_names.h"
 #include "scene/scene_string_names.h"
 
 
 void Material::set_next_pass(const Ref<Material> &p_pass) {
 void Material::set_next_pass(const Ref<Material> &p_pass) {
@@ -80,6 +81,14 @@ void Material::_validate_property(PropertyInfo &property) const {
 	}
 	}
 }
 }
 
 
+void Material::inspect_native_shader_code() {
+	SceneTree *st = Object::cast_to<SceneTree>(OS::get_singleton()->get_main_loop());
+	RID shader = get_shader_rid();
+	if (st && shader.is_valid()) {
+		st->call_group("_native_shader_source_visualizer", "_inspect_shader", shader);
+	}
+}
+
 void Material::_bind_methods() {
 void Material::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_next_pass", "next_pass"), &Material::set_next_pass);
 	ClassDB::bind_method(D_METHOD("set_next_pass", "next_pass"), &Material::set_next_pass);
 	ClassDB::bind_method(D_METHOD("get_next_pass"), &Material::get_next_pass);
 	ClassDB::bind_method(D_METHOD("get_next_pass"), &Material::get_next_pass);
@@ -87,6 +96,9 @@ void Material::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_render_priority", "priority"), &Material::set_render_priority);
 	ClassDB::bind_method(D_METHOD("set_render_priority", "priority"), &Material::set_render_priority);
 	ClassDB::bind_method(D_METHOD("get_render_priority"), &Material::get_render_priority);
 	ClassDB::bind_method(D_METHOD("get_render_priority"), &Material::get_render_priority);
 
 
+	ClassDB::bind_method(D_METHOD("inspect_native_shader_code"), &Material::inspect_native_shader_code);
+	ClassDB::set_method_flags(get_class_static(), _scs_create("inspect_native_shader_code"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
+
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "render_priority", PROPERTY_HINT_RANGE, itos(RENDER_PRIORITY_MIN) + "," + itos(RENDER_PRIORITY_MAX) + ",1"), "set_render_priority", "get_render_priority");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "render_priority", PROPERTY_HINT_RANGE, itos(RENDER_PRIORITY_MIN) + "," + itos(RENDER_PRIORITY_MAX) + ",1"), "set_render_priority", "get_render_priority");
 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "next_pass", PROPERTY_HINT_RESOURCE_TYPE, "Material"), "set_next_pass", "get_next_pass");
 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "next_pass", PROPERTY_HINT_RESOURCE_TYPE, "Material"), "set_next_pass", "get_next_pass");
 
 
@@ -260,6 +272,13 @@ Shader::Mode ShaderMaterial::get_shader_mode() const {
 		return Shader::MODE_SPATIAL;
 		return Shader::MODE_SPATIAL;
 	}
 	}
 }
 }
+RID ShaderMaterial::get_shader_rid() const {
+	if (shader.is_valid()) {
+		return shader->get_rid();
+	} else {
+		return RID();
+	}
+}
 
 
 ShaderMaterial::ShaderMaterial() {
 ShaderMaterial::ShaderMaterial() {
 }
 }

+ 6 - 1
scene/resources/material.h

@@ -47,6 +47,8 @@ class Material : public Resource {
 	Ref<Material> next_pass;
 	Ref<Material> next_pass;
 	int render_priority;
 	int render_priority;
 
 
+	void inspect_native_shader_code();
+
 protected:
 protected:
 	_FORCE_INLINE_ RID _get_material() const { return material; }
 	_FORCE_INLINE_ RID _get_material() const { return material; }
 	static void _bind_methods();
 	static void _bind_methods();
@@ -66,6 +68,7 @@ public:
 	int get_render_priority() const;
 	int get_render_priority() const;
 
 
 	virtual RID get_rid() const override;
 	virtual RID get_rid() const override;
+	virtual RID get_shader_rid() const = 0;
 
 
 	virtual Shader::Mode get_shader_mode() const = 0;
 	virtual Shader::Mode get_shader_mode() const = 0;
 	Material();
 	Material();
@@ -100,6 +103,8 @@ public:
 
 
 	virtual Shader::Mode get_shader_mode() const override;
 	virtual Shader::Mode get_shader_mode() const override;
 
 
+	virtual RID get_shader_rid() const override;
+
 	ShaderMaterial();
 	ShaderMaterial();
 	~ShaderMaterial();
 	~ShaderMaterial();
 };
 };
@@ -736,7 +741,7 @@ public:
 
 
 	static RID get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard = false, bool p_billboard_y = false);
 	static RID get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard = false, bool p_billboard_y = false);
 
 
-	RID get_shader_rid() const;
+	virtual RID get_shader_rid() const override;
 
 
 	virtual Shader::Mode get_shader_mode() const override;
 	virtual Shader::Mode get_shader_mode() const override;
 
 

+ 1 - 1
scene/resources/particles_material.h

@@ -340,7 +340,7 @@ public:
 	void set_sub_emitter_keep_velocity(bool p_enable);
 	void set_sub_emitter_keep_velocity(bool p_enable);
 	bool get_sub_emitter_keep_velocity() const;
 	bool get_sub_emitter_keep_velocity() const;
 
 
-	RID get_shader_rid() const;
+	virtual RID get_shader_rid() const override;
 
 
 	virtual Shader::Mode get_shader_mode() const override;
 	virtual Shader::Mode get_shader_mode() const override;
 
 

+ 3 - 3
scene/resources/sky_material.h

@@ -89,7 +89,7 @@ public:
 	float get_sun_curve() const;
 	float get_sun_curve() const;
 
 
 	virtual Shader::Mode get_shader_mode() const override;
 	virtual Shader::Mode get_shader_mode() const override;
-	RID get_shader_rid() const;
+	virtual RID get_shader_rid() const override;
 
 
 	ProceduralSkyMaterial();
 	ProceduralSkyMaterial();
 	~ProceduralSkyMaterial();
 	~ProceduralSkyMaterial();
@@ -114,7 +114,7 @@ public:
 	Ref<Texture2D> get_panorama() const;
 	Ref<Texture2D> get_panorama() const;
 
 
 	virtual Shader::Mode get_shader_mode() const override;
 	virtual Shader::Mode get_shader_mode() const override;
-	RID get_shader_rid() const;
+	virtual RID get_shader_rid() const override;
 
 
 	PanoramaSkyMaterial();
 	PanoramaSkyMaterial();
 	~PanoramaSkyMaterial();
 	~PanoramaSkyMaterial();
@@ -180,7 +180,7 @@ public:
 	Ref<Texture2D> get_night_sky() const;
 	Ref<Texture2D> get_night_sky() const;
 
 
 	virtual Shader::Mode get_shader_mode() const override;
 	virtual Shader::Mode get_shader_mode() const override;
-	RID get_shader_rid() const;
+	virtual RID get_shader_rid() const override;
 
 
 	PhysicalSkyMaterial();
 	PhysicalSkyMaterial();
 	~PhysicalSkyMaterial();
 	~PhysicalSkyMaterial();

+ 5 - 0
servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp

@@ -2239,6 +2239,11 @@ Variant RendererCanvasRenderRD::ShaderData::get_default_parameter(const StringNa
 	return Variant();
 	return Variant();
 }
 }
 
 
+RS::ShaderNativeSourceCode RendererCanvasRenderRD::ShaderData::get_native_source_code() const {
+	RendererCanvasRenderRD *canvas_singleton = (RendererCanvasRenderRD *)RendererCanvasRender::singleton;
+	return canvas_singleton->shader.canvas_shader.version_get_native_source_code(version);
+}
+
 RendererCanvasRenderRD::ShaderData::ShaderData() {
 RendererCanvasRenderRD::ShaderData::ShaderData() {
 	valid = false;
 	valid = false;
 	uses_screen_texture = false;
 	uses_screen_texture = false;

+ 2 - 0
servers/rendering/renderer_rd/renderer_canvas_render_rd.h

@@ -188,6 +188,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
 		virtual bool is_animated() const;
 		virtual bool is_animated() const;
 		virtual bool casts_shadows() const;
 		virtual bool casts_shadows() const;
 		virtual Variant get_default_parameter(const StringName &p_parameter) const;
 		virtual Variant get_default_parameter(const StringName &p_parameter) const;
+		virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+
 		ShaderData();
 		ShaderData();
 		virtual ~ShaderData();
 		virtual ~ShaderData();
 	};
 	};

+ 6 - 0
servers/rendering/renderer_rd/renderer_scene_render_forward.cpp

@@ -394,6 +394,12 @@ Variant RendererSceneRenderForward::ShaderData::get_default_parameter(const Stri
 	return Variant();
 	return Variant();
 }
 }
 
 
+RS::ShaderNativeSourceCode RendererSceneRenderForward::ShaderData::get_native_source_code() const {
+	RendererSceneRenderForward *scene_singleton = (RendererSceneRenderForward *)RendererSceneRenderForward::singleton;
+
+	return scene_singleton->shader.scene_shader.version_get_native_source_code(version);
+}
+
 RendererSceneRenderForward::ShaderData::ShaderData() {
 RendererSceneRenderForward::ShaderData::ShaderData() {
 	valid = false;
 	valid = false;
 	uses_screen_texture = false;
 	uses_screen_texture = false;

+ 2 - 0
servers/rendering/renderer_rd/renderer_scene_render_forward.h

@@ -169,6 +169,8 @@ class RendererSceneRenderForward : public RendererSceneRenderRD {
 		virtual bool is_animated() const;
 		virtual bool is_animated() const;
 		virtual bool casts_shadows() const;
 		virtual bool casts_shadows() const;
 		virtual Variant get_default_parameter(const StringName &p_parameter) const;
 		virtual Variant get_default_parameter(const StringName &p_parameter) const;
+		virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+
 		ShaderData();
 		ShaderData();
 		virtual ~ShaderData();
 		virtual ~ShaderData();
 	};
 	};

+ 6 - 0
servers/rendering/renderer_rd/renderer_scene_render_rd.cpp

@@ -2674,6 +2674,12 @@ Variant RendererSceneRenderRD::SkyShaderData::get_default_parameter(const String
 	return Variant();
 	return Variant();
 }
 }
 
 
+RS::ShaderNativeSourceCode RendererSceneRenderRD::SkyShaderData::get_native_source_code() const {
+	RendererSceneRenderRD *scene_singleton = (RendererSceneRenderRD *)RendererSceneRenderRD::singleton;
+
+	return scene_singleton->sky_shader.shader.version_get_native_source_code(version);
+}
+
 RendererSceneRenderRD::SkyShaderData::SkyShaderData() {
 RendererSceneRenderRD::SkyShaderData::SkyShaderData() {
 	valid = false;
 	valid = false;
 }
 }

+ 1 - 0
servers/rendering/renderer_rd/renderer_scene_render_rd.h

@@ -233,6 +233,7 @@ private:
 		virtual bool is_animated() const;
 		virtual bool is_animated() const;
 		virtual bool casts_shadows() const;
 		virtual bool casts_shadows() const;
 		virtual Variant get_default_parameter(const StringName &p_parameter) const;
 		virtual Variant get_default_parameter(const StringName &p_parameter) const;
+		virtual RS::ShaderNativeSourceCode get_native_source_code() const;
 		SkyShaderData();
 		SkyShaderData();
 		virtual ~SkyShaderData();
 		virtual ~SkyShaderData();
 	};
 	};

+ 13 - 0
servers/rendering/renderer_rd/renderer_storage_rd.cpp

@@ -1499,6 +1499,15 @@ void RendererStorageRD::shader_set_data_request_function(ShaderType p_shader_typ
 	shader_data_request_func[p_shader_type] = p_function;
 	shader_data_request_func[p_shader_type] = p_function;
 }
 }
 
 
+RS::ShaderNativeSourceCode RendererStorageRD::shader_get_native_source_code(RID p_shader) const {
+	Shader *shader = shader_owner.getornull(p_shader);
+	ERR_FAIL_COND_V(!shader, RS::ShaderNativeSourceCode());
+	if (shader->data) {
+		return shader->data->get_native_source_code();
+	}
+	return RS::ShaderNativeSourceCode();
+}
+
 /* COMMON MATERIAL API */
 /* COMMON MATERIAL API */
 
 
 RID RendererStorageRD::material_create() {
 RID RendererStorageRD::material_create() {
@@ -4823,6 +4832,10 @@ Variant RendererStorageRD::ParticlesShaderData::get_default_parameter(const Stri
 	return Variant();
 	return Variant();
 }
 }
 
 
+RS::ShaderNativeSourceCode RendererStorageRD::ParticlesShaderData::get_native_source_code() const {
+	return base_singleton->particles_shader.shader.version_get_native_source_code(version);
+}
+
 RendererStorageRD::ParticlesShaderData::ParticlesShaderData() {
 RendererStorageRD::ParticlesShaderData::ParticlesShaderData() {
 	valid = false;
 	valid = false;
 }
 }

+ 6 - 0
servers/rendering/renderer_rd/renderer_storage_rd.h

@@ -127,6 +127,8 @@ public:
 		virtual bool is_animated() const = 0;
 		virtual bool is_animated() const = 0;
 		virtual bool casts_shadows() const = 0;
 		virtual bool casts_shadows() const = 0;
 		virtual Variant get_default_parameter(const StringName &p_parameter) const = 0;
 		virtual Variant get_default_parameter(const StringName &p_parameter) const = 0;
+		virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); }
+
 		virtual ~ShaderData() {}
 		virtual ~ShaderData() {}
 	};
 	};
 
 
@@ -840,6 +842,8 @@ private:
 		virtual bool is_animated() const;
 		virtual bool is_animated() const;
 		virtual bool casts_shadows() const;
 		virtual bool casts_shadows() const;
 		virtual Variant get_default_parameter(const StringName &p_parameter) const;
 		virtual Variant get_default_parameter(const StringName &p_parameter) const;
+		virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+
 		ParticlesShaderData();
 		ParticlesShaderData();
 		virtual ~ParticlesShaderData();
 		virtual ~ParticlesShaderData();
 	};
 	};
@@ -1339,6 +1343,8 @@ public:
 	Variant shader_get_param_default(RID p_shader, const StringName &p_param) const;
 	Variant shader_get_param_default(RID p_shader, const StringName &p_param) const;
 	void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function);
 	void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function);
 
 
+	virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const;
+
 	/* COMMON MATERIAL API */
 	/* COMMON MATERIAL API */
 
 
 	RID material_create();
 	RID material_create();

+ 121 - 0
servers/rendering/renderer_rd/shader_rd.cpp

@@ -351,6 +351,127 @@ void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) {
 	}
 	}
 }
 }
 
 
+RS::ShaderNativeSourceCode ShaderRD::version_get_native_source_code(RID p_version) {
+	Version *version = version_owner.getornull(p_version);
+	RS::ShaderNativeSourceCode source_code;
+	ERR_FAIL_COND_V(!version, source_code);
+
+	source_code.versions.resize(variant_defines.size());
+
+	for (int i = 0; i < source_code.versions.size(); i++) {
+		if (!is_compute) {
+			//vertex stage
+
+			StringBuilder builder;
+
+			builder.append(vertex_codev.get_data()); // version info (if exists)
+			builder.append("\n"); //make sure defines begin at newline
+			builder.append(general_defines.get_data());
+			builder.append(variant_defines[i].get_data());
+
+			for (int j = 0; j < version->custom_defines.size(); j++) {
+				builder.append(version->custom_defines[j].get_data());
+			}
+
+			builder.append(vertex_code0.get_data()); //first part of vertex
+
+			builder.append(version->uniforms.get_data()); //uniforms (same for vertex and fragment)
+
+			builder.append(vertex_code1.get_data()); //second part of vertex
+
+			builder.append(version->vertex_globals.get_data()); // vertex globals
+
+			builder.append(vertex_code2.get_data()); //third part of vertex
+
+			builder.append(version->vertex_code.get_data()); // code
+
+			builder.append(vertex_code3.get_data()); //fourth of vertex
+
+			RS::ShaderNativeSourceCode::Version::Stage stage;
+			stage.name = "vertex";
+			stage.code = builder.as_string();
+
+			source_code.versions.write[i].stages.push_back(stage);
+		}
+
+		if (!is_compute) {
+			//fragment stage
+
+			StringBuilder builder;
+
+			builder.append(fragment_codev.get_data()); // version info (if exists)
+			builder.append("\n"); //make sure defines begin at newline
+
+			builder.append(general_defines.get_data());
+			builder.append(variant_defines[i].get_data());
+			for (int j = 0; j < version->custom_defines.size(); j++) {
+				builder.append(version->custom_defines[j].get_data());
+			}
+
+			builder.append(fragment_code0.get_data()); //first part of fragment
+
+			builder.append(version->uniforms.get_data()); //uniforms (same for fragment and fragment)
+
+			builder.append(fragment_code1.get_data()); //first part of fragment
+
+			builder.append(version->fragment_globals.get_data()); // fragment globals
+
+			builder.append(fragment_code2.get_data()); //third part of fragment
+
+			builder.append(version->fragment_light.get_data()); // fragment light
+
+			builder.append(fragment_code3.get_data()); //fourth part of fragment
+
+			builder.append(version->fragment_code.get_data()); // fragment code
+
+			builder.append(fragment_code4.get_data()); //fourth part of fragment
+
+			RS::ShaderNativeSourceCode::Version::Stage stage;
+			stage.name = "fragment";
+			stage.code = builder.as_string();
+
+			source_code.versions.write[i].stages.push_back(stage);
+		}
+
+		if (is_compute) {
+			//compute stage
+
+			StringBuilder builder;
+
+			builder.append(compute_codev.get_data()); // version info (if exists)
+			builder.append("\n"); //make sure defines begin at newline
+			builder.append(general_defines.get_data());
+			builder.append(variant_defines[i].get_data());
+
+			for (int j = 0; j < version->custom_defines.size(); j++) {
+				builder.append(version->custom_defines[j].get_data());
+			}
+
+			builder.append(compute_code0.get_data()); //first part of compute
+
+			builder.append(version->uniforms.get_data()); //uniforms (same for compute and fragment)
+
+			builder.append(compute_code1.get_data()); //second part of compute
+
+			builder.append(version->compute_globals.get_data()); // compute globals
+
+			builder.append(compute_code2.get_data()); //third part of compute
+
+			builder.append(version->compute_code.get_data()); // code
+
+			builder.append(compute_code3.get_data()); //fourth of compute
+
+			RS::ShaderNativeSourceCode::Version::Stage stage;
+			stage.name = "compute";
+			stage.code = builder.as_string();
+
+			source_code.versions.write[i].stages.push_back(stage);
+		}
+	}
+
+	return source_code;
+}
+
 void ShaderRD::_compile_version(Version *p_version) {
 void ShaderRD::_compile_version(Version *p_version) {
 	_clear_version(p_version);
 	_clear_version(p_version);
 
 

+ 3 - 0
servers/rendering/renderer_rd/shader_rd.h

@@ -36,6 +36,7 @@
 #include "core/templates/map.h"
 #include "core/templates/map.h"
 #include "core/templates/rid_owner.h"
 #include "core/templates/rid_owner.h"
 #include "core/variant/variant.h"
 #include "core/variant/variant.h"
+#include "servers/rendering_server.h"
 
 
 #include <stdio.h>
 #include <stdio.h>
 /**
 /**
@@ -133,6 +134,8 @@ public:
 	void set_variant_enabled(int p_variant, bool p_enabled);
 	void set_variant_enabled(int p_variant, bool p_enabled);
 	bool is_variant_enabled(int p_variant) const;
 	bool is_variant_enabled(int p_variant) const;
 
 
+	RS::ShaderNativeSourceCode version_get_native_source_code(RID p_version);
+
 	void initialize(const Vector<String> &p_variant_defines, const String &p_general_defines = "");
 	void initialize(const Vector<String> &p_variant_defines, const String &p_general_defines = "");
 	virtual ~ShaderRD();
 	virtual ~ShaderRD();
 };
 };

+ 2 - 0
servers/rendering/renderer_storage.h

@@ -179,6 +179,8 @@ public:
 	virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0;
 	virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0;
 	virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0;
 	virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0;
 
 
+	virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0;
+
 	/* COMMON MATERIAL API */
 	/* COMMON MATERIAL API */
 
 
 	virtual RID material_create() = 0;
 	virtual RID material_create() = 0;

+ 2 - 0
servers/rendering/rendering_server_default.h

@@ -219,6 +219,8 @@ public:
 	BIND2RC(RID, shader_get_default_texture_param, RID, const StringName &)
 	BIND2RC(RID, shader_get_default_texture_param, RID, const StringName &)
 	BIND2RC(Variant, shader_get_param_default, RID, const StringName &)
 	BIND2RC(Variant, shader_get_param_default, RID, const StringName &)
 
 
+	BIND1RC(ShaderNativeSourceCode, shader_get_native_source_code, RID)
+
 	/* COMMON MATERIAL API */
 	/* COMMON MATERIAL API */
 
 
 	BIND0R(RID, material_create)
 	BIND0R(RID, material_create)

+ 2 - 0
servers/rendering/rendering_server_wrap_mt.h

@@ -129,6 +129,8 @@ public:
 	FUNC2RC(RID, shader_get_default_texture_param, RID, const StringName &)
 	FUNC2RC(RID, shader_get_default_texture_param, RID, const StringName &)
 	FUNC2RC(Variant, shader_get_param_default, RID, const StringName &)
 	FUNC2RC(Variant, shader_get_param_default, RID, const StringName &)
 
 
+	FUNC1RC(ShaderNativeSourceCode, shader_get_native_source_code, RID)
+
 	/* COMMON MATERIAL API */
 	/* COMMON MATERIAL API */
 
 
 	FUNCRID(material)
 	FUNCRID(material)

+ 13 - 0
servers/rendering_server.h

@@ -179,6 +179,19 @@ public:
 	virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0;
 	virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0;
 	virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0;
 	virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0;
 
 
+	struct ShaderNativeSourceCode {
+		struct Version {
+			struct Stage {
+				String name;
+				String code;
+			};
+			Vector<Stage> stages;
+		};
+		Vector<Version> versions;
+	};
+
+	virtual ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0;
+
 	/* COMMON MATERIAL API */
 	/* COMMON MATERIAL API */
 
 
 	enum {
 	enum {