Merge pull request #44950 from reduz/shader-debugger

Added ability to visualize native shaders
This commit is contained in:
Rémi Verschelde 2021-01-06 16:28:45 +01:00 committed by GitHub
commit a7baf01352
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 342 additions and 6 deletions

View File

@ -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"));
}

View File

@ -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

View File

@ -6519,6 +6519,9 @@ EditorNode::EditorNode() {
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);
gui_base->add_child(orphan_resources);

View File

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

View File

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

View File

@ -36,6 +36,7 @@
#include "editor/editor_settings.h"
#endif
#include "scene/main/scene_tree.h"
#include "scene/scene_string_names.h"
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() {
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);
@ -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("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::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;
}
}
RID ShaderMaterial::get_shader_rid() const {
if (shader.is_valid()) {
return shader->get_rid();
} else {
return RID();
}
}
ShaderMaterial::ShaderMaterial() {
}

View File

@ -47,6 +47,8 @@ class Material : public Resource {
Ref<Material> next_pass;
int render_priority;
void inspect_native_shader_code();
protected:
_FORCE_INLINE_ RID _get_material() const { return material; }
static void _bind_methods();
@ -66,6 +68,7 @@ public:
int get_render_priority() const;
virtual RID get_rid() const override;
virtual RID get_shader_rid() const = 0;
virtual Shader::Mode get_shader_mode() const = 0;
Material();
@ -100,6 +103,8 @@ public:
virtual Shader::Mode get_shader_mode() const override;
virtual RID get_shader_rid() const override;
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);
RID get_shader_rid() const;
virtual RID get_shader_rid() const override;
virtual Shader::Mode get_shader_mode() const override;

View File

@ -340,7 +340,7 @@ public:
void set_sub_emitter_keep_velocity(bool p_enable);
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;

View File

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

View File

@ -2239,6 +2239,11 @@ Variant RendererCanvasRenderRD::ShaderData::get_default_parameter(const StringNa
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() {
valid = false;
uses_screen_texture = false;

View File

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

View File

@ -394,6 +394,12 @@ Variant RendererSceneRenderForward::ShaderData::get_default_parameter(const Stri
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() {
valid = false;
uses_screen_texture = false;

View File

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

View File

@ -2674,6 +2674,12 @@ Variant RendererSceneRenderRD::SkyShaderData::get_default_parameter(const String
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() {
valid = false;
}

View File

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

View File

@ -1499,6 +1499,15 @@ void RendererStorageRD::shader_set_data_request_function(ShaderType p_shader_typ
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 */
RID RendererStorageRD::material_create() {
@ -4823,6 +4832,10 @@ Variant RendererStorageRD::ParticlesShaderData::get_default_parameter(const Stri
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() {
valid = false;
}

View File

@ -127,6 +127,8 @@ public:
virtual bool is_animated() const = 0;
virtual bool casts_shadows() 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() {}
};
@ -840,6 +842,8 @@ private:
virtual bool is_animated() const;
virtual bool casts_shadows() const;
virtual Variant get_default_parameter(const StringName &p_parameter) const;
virtual RS::ShaderNativeSourceCode get_native_source_code() const;
ParticlesShaderData();
virtual ~ParticlesShaderData();
};
@ -1339,6 +1343,8 @@ public:
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);
virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const;
/* COMMON MATERIAL API */
RID material_create();

View File

@ -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) {
_clear_version(p_version);

View File

@ -36,6 +36,7 @@
#include "core/templates/map.h"
#include "core/templates/rid_owner.h"
#include "core/variant/variant.h"
#include "servers/rendering_server.h"
#include <stdio.h>
/**
@ -133,6 +134,8 @@ public:
void set_variant_enabled(int p_variant, bool p_enabled);
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 = "");
virtual ~ShaderRD();
};

View File

@ -179,6 +179,8 @@ public:
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 RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0;
/* COMMON MATERIAL API */
virtual RID material_create() = 0;

View File

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

View File

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

View File

@ -179,6 +179,19 @@ public:
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;
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 */
enum {