You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-22 15:06:45 +00:00
Fix several shader preprocessor include issues
This commit is contained in:
@@ -383,11 +383,12 @@ void ShaderTextEditor::_code_complete_script(const String &p_code, List<ScriptLa
|
|||||||
List<ScriptLanguage::CodeCompletionOption> pp_defines;
|
List<ScriptLanguage::CodeCompletionOption> pp_defines;
|
||||||
ShaderPreprocessor preprocessor;
|
ShaderPreprocessor preprocessor;
|
||||||
String code;
|
String code;
|
||||||
complete_from_path = (shader.is_valid() ? shader->get_path() : shader_inc->get_path()).get_base_dir();
|
String resource_path = (shader.is_valid() ? shader->get_path() : shader_inc->get_path());
|
||||||
|
complete_from_path = resource_path.get_base_dir();
|
||||||
if (!complete_from_path.ends_with("/")) {
|
if (!complete_from_path.ends_with("/")) {
|
||||||
complete_from_path += "/";
|
complete_from_path += "/";
|
||||||
}
|
}
|
||||||
preprocessor.preprocess(p_code, "", code, nullptr, nullptr, nullptr, nullptr, &pp_options, &pp_defines, _complete_include_paths);
|
preprocessor.preprocess(p_code, resource_path, code, nullptr, nullptr, nullptr, nullptr, &pp_options, &pp_defines, _complete_include_paths);
|
||||||
complete_from_path = String();
|
complete_from_path = String();
|
||||||
if (pp_options.size()) {
|
if (pp_options.size()) {
|
||||||
for (const ScriptLanguage::CodeCompletionOption &E : pp_options) {
|
for (const ScriptLanguage::CodeCompletionOption &E : pp_options) {
|
||||||
|
|||||||
@@ -55,6 +55,12 @@ void Shader::set_path(const String &p_path, bool p_take_over) {
|
|||||||
RS::get_singleton()->shader_set_path_hint(shader, p_path);
|
RS::get_singleton()->shader_set_path_hint(shader, p_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Shader::set_include_path(const String &p_path) {
|
||||||
|
// Used only if the shader does not have a resource path set,
|
||||||
|
// for example during loading stage or when created by code.
|
||||||
|
include_path = p_path;
|
||||||
|
}
|
||||||
|
|
||||||
void Shader::set_code(const String &p_code) {
|
void Shader::set_code(const String &p_code) {
|
||||||
for (Ref<ShaderInclude> E : include_dependencies) {
|
for (Ref<ShaderInclude> E : include_dependencies) {
|
||||||
E->disconnect(SNAME("changed"), callable_mp(this, &Shader::_dependency_changed));
|
E->disconnect(SNAME("changed"), callable_mp(this, &Shader::_dependency_changed));
|
||||||
@@ -80,11 +86,15 @@ void Shader::set_code(const String &p_code) {
|
|||||||
HashSet<Ref<ShaderInclude>> new_include_dependencies;
|
HashSet<Ref<ShaderInclude>> new_include_dependencies;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
String path = get_path();
|
||||||
|
if (path.is_empty()) {
|
||||||
|
path = include_path;
|
||||||
|
}
|
||||||
// Preprocessor must run here and not in the server because:
|
// Preprocessor must run here and not in the server because:
|
||||||
// 1) Need to keep track of include dependencies at resource level
|
// 1) Need to keep track of include dependencies at resource level
|
||||||
// 2) Server does not do interaction with Resource filetypes, this is a scene level feature.
|
// 2) Server does not do interaction with Resource filetypes, this is a scene level feature.
|
||||||
ShaderPreprocessor preprocessor;
|
ShaderPreprocessor preprocessor;
|
||||||
preprocessor.preprocess(p_code, "", pp_code, nullptr, nullptr, nullptr, &new_include_dependencies);
|
preprocessor.preprocess(p_code, path, pp_code, nullptr, nullptr, nullptr, &new_include_dependencies);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This ensures previous include resources are not freed and then re-loaded during parse (which would make compiling slower)
|
// This ensures previous include resources are not freed and then re-loaded during parse (which would make compiling slower)
|
||||||
@@ -231,6 +241,7 @@ Ref<Resource> ResourceFormatLoaderShader::load(const String &p_path, const Strin
|
|||||||
String str;
|
String str;
|
||||||
str.parse_utf8((const char *)buffer.ptr(), buffer.size());
|
str.parse_utf8((const char *)buffer.ptr(), buffer.size());
|
||||||
|
|
||||||
|
shader->set_include_path(p_path);
|
||||||
shader->set_code(str);
|
shader->set_code(str);
|
||||||
|
|
||||||
if (r_error) {
|
if (r_error) {
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ private:
|
|||||||
Mode mode = MODE_SPATIAL;
|
Mode mode = MODE_SPATIAL;
|
||||||
HashSet<Ref<ShaderInclude>> include_dependencies;
|
HashSet<Ref<ShaderInclude>> include_dependencies;
|
||||||
String code;
|
String code;
|
||||||
|
String include_path;
|
||||||
|
|
||||||
HashMap<StringName, HashMap<int, Ref<Texture2D>>> default_textures;
|
HashMap<StringName, HashMap<int, Ref<Texture2D>>> default_textures;
|
||||||
|
|
||||||
@@ -72,6 +73,7 @@ public:
|
|||||||
virtual Mode get_mode() const;
|
virtual Mode get_mode() const;
|
||||||
|
|
||||||
virtual void set_path(const String &p_path, bool p_take_over = false) override;
|
virtual void set_path(const String &p_path, bool p_take_over = false) override;
|
||||||
|
void set_include_path(const String &p_path);
|
||||||
|
|
||||||
void set_code(const String &p_code);
|
void set_code(const String &p_code);
|
||||||
String get_code() const;
|
String get_code() const;
|
||||||
|
|||||||
@@ -45,9 +45,14 @@ void ShaderInclude::set_code(const String &p_code) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
String path = get_path();
|
||||||
|
if (path.is_empty()) {
|
||||||
|
path = include_path;
|
||||||
|
}
|
||||||
|
|
||||||
String pp_code;
|
String pp_code;
|
||||||
ShaderPreprocessor preprocessor;
|
ShaderPreprocessor preprocessor;
|
||||||
preprocessor.preprocess(p_code, "", pp_code, nullptr, nullptr, nullptr, &new_dependencies);
|
preprocessor.preprocess(p_code, path, pp_code, nullptr, nullptr, nullptr, &new_dependencies);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This ensures previous include resources are not freed and then re-loaded during parse (which would make compiling slower)
|
// This ensures previous include resources are not freed and then re-loaded during parse (which would make compiling slower)
|
||||||
@@ -64,6 +69,10 @@ String ShaderInclude::get_code() const {
|
|||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShaderInclude::set_include_path(const String &p_path) {
|
||||||
|
include_path = p_path;
|
||||||
|
}
|
||||||
|
|
||||||
void ShaderInclude::_bind_methods() {
|
void ShaderInclude::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_code", "code"), &ShaderInclude::set_code);
|
ClassDB::bind_method(D_METHOD("set_code", "code"), &ShaderInclude::set_code);
|
||||||
ClassDB::bind_method(D_METHOD("get_code"), &ShaderInclude::get_code);
|
ClassDB::bind_method(D_METHOD("get_code"), &ShaderInclude::get_code);
|
||||||
@@ -86,6 +95,7 @@ Ref<Resource> ResourceFormatLoaderShaderInclude::load(const String &p_path, cons
|
|||||||
String str;
|
String str;
|
||||||
str.parse_utf8((const char *)buffer.ptr(), buffer.size());
|
str.parse_utf8((const char *)buffer.ptr(), buffer.size());
|
||||||
|
|
||||||
|
shader_inc->set_include_path(p_path);
|
||||||
shader_inc->set_code(str);
|
shader_inc->set_code(str);
|
||||||
|
|
||||||
if (r_error) {
|
if (r_error) {
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ class ShaderInclude : public Resource {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
String code;
|
String code;
|
||||||
|
String include_path;
|
||||||
HashSet<Ref<ShaderInclude>> dependencies;
|
HashSet<Ref<ShaderInclude>> dependencies;
|
||||||
void _dependency_changed();
|
void _dependency_changed();
|
||||||
|
|
||||||
@@ -51,6 +52,8 @@ protected:
|
|||||||
public:
|
public:
|
||||||
void set_code(const String &p_text);
|
void set_code(const String &p_text);
|
||||||
String get_code() const;
|
String get_code() const;
|
||||||
|
|
||||||
|
void set_include_path(const String &p_path);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResourceFormatLoaderShaderInclude : public ResourceFormatLoader {
|
class ResourceFormatLoaderShaderInclude : public ResourceFormatLoader {
|
||||||
|
|||||||
@@ -674,6 +674,11 @@ void ShaderPreprocessor::process_include(Tokenizer *p_tokenizer) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
path = path.simplify_path();
|
||||||
|
if (path.is_relative_path()) {
|
||||||
|
path = state->current_filename.get_base_dir().path_join(path);
|
||||||
|
}
|
||||||
|
|
||||||
Ref<Resource> res = ResourceLoader::load(path);
|
Ref<Resource> res = ResourceLoader::load(path);
|
||||||
if (res.is_null()) {
|
if (res.is_null()) {
|
||||||
set_error(RTR("Shader include load failed. Does the shader include exist? Is there a cyclic dependency?"), line);
|
set_error(RTR("Shader include load failed. Does the shader include exist? Is there a cyclic dependency?"), line);
|
||||||
|
|||||||
Reference in New Issue
Block a user