From 6dcf74922f46b086ad394c19fd6ce083a635b290 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 13 Mar 2021 16:02:41 +0200 Subject: [PATCH] Add GLSL keywords for overriding functions Overriding with a plain redefinition is now deprecated. --- shaderlib/common.glsl | 16 ++++++++-------- shaderlib/cooktorrance.glsl | 10 +++++----- shaderlib/phong.glsl | 10 +++++----- shaderlib/shadow.glsl | 2 +- source/glsl/generate.cpp | 9 +++++++++ source/glsl/parser.cpp | 5 +++++ source/glsl/syntax.cpp | 4 ++++ source/glsl/syntax.h | 2 ++ tests/glsl/function_override.glsl | 22 ++++++++++++++++++++++ 9 files changed, 61 insertions(+), 19 deletions(-) create mode 100644 tests/glsl/function_override.glsl diff --git a/shaderlib/common.glsl b/shaderlib/common.glsl index eb191e45..9e794f1d 100644 --- a/shaderlib/common.glsl +++ b/shaderlib/common.glsl @@ -4,22 +4,22 @@ import shadow; layout(constant_id=auto) const bool use_normal_map = false; #pragma MSP stage(vertex) -vec4 get_vertex_position() +virtual vec4 get_vertex_position() { return vertex; } -vec3 get_vertex_normal() +virtual vec3 get_vertex_normal() { return normal; } -vec4 transform_position(vec4 pos) +virtual vec4 transform_position(vec4 pos) { return eye_obj_matrix*pos; } -vec3 transform_normal(vec3 nor) +virtual vec3 transform_normal(vec3 nor) { return eye_obj_normal_matrix*nor; } @@ -52,7 +52,7 @@ void standard_transform() shadow_transform(eye_vertex); } -void custom_transform() +virtual void custom_transform() { } @@ -64,7 +64,7 @@ void main() } #pragma MSP stage(fragment) -vec3 get_fragment_normal() +virtual vec3 get_fragment_normal() { if(use_normal_map) return normalize(texture(normal_map, texcoord.xy).xyz*2.0-1.0); @@ -72,12 +72,12 @@ vec3 get_fragment_normal() return vec3(0.0, 0.0, 1.0); } -vec4 get_environment_sample(vec3 direction) +virtual vec4 get_environment_sample(vec3 direction) { return texture(environment_map, direction); } -vec3 get_reflection(vec3 normal, vec3 look) +virtual vec3 get_reflection(vec3 normal, vec3 look) { vec3 reflect_dir = reflect(look, normal); if(use_normal_map) diff --git a/shaderlib/cooktorrance.glsl b/shaderlib/cooktorrance.glsl index 89b4c99c..c866058d 100644 --- a/shaderlib/cooktorrance.glsl +++ b/shaderlib/cooktorrance.glsl @@ -12,7 +12,7 @@ layout(constant_id=auto) const bool use_emission_map = false; const float PI = 3.1415926535; #pragma MSP stage(fragment) -vec4 get_base_color() +virtual vec4 get_base_color() { if(use_base_color_map) return texture(base_color_map, texcoord.xy); @@ -20,7 +20,7 @@ vec4 get_base_color() return pbr_material.base_color; } -float get_metalness_value() +virtual float get_metalness_value() { if(use_metalness_map) return texture(metalness_map, texcoord.xy).r; @@ -28,7 +28,7 @@ float get_metalness_value() return pbr_material.metalness; } -float get_roughness_value() +virtual float get_roughness_value() { if(use_roughness_map) return texture(roughness_map, texcoord.xy).r; @@ -36,7 +36,7 @@ float get_roughness_value() return pbr_material.roughness; } -float get_occlusion_value() +virtual float get_occlusion_value() { if(use_occlusion_map) return texture(occlusion_map, texcoord.xy).r; @@ -44,7 +44,7 @@ float get_occlusion_value() return 1.0; } -vec3 get_emission_color() +virtual vec3 get_emission_color() { if(use_emission_map) return texture(emission_map, texcoord.xy).rgb; diff --git a/shaderlib/phong.glsl b/shaderlib/phong.glsl index 56fa68c7..f9d8d1e7 100644 --- a/shaderlib/phong.glsl +++ b/shaderlib/phong.glsl @@ -14,7 +14,7 @@ layout(constant_id=auto) const bool use_sky = false; layout(constant_id=auto) const bool use_fog = false; #pragma MSP stage(fragment) -vec4 get_diffuse_color() +virtual vec4 get_diffuse_color() { if(use_diffuse_map) return texture(diffuse_map, texcoord.xy); @@ -22,7 +22,7 @@ vec4 get_diffuse_color() return basic_material.diffuse; } -vec3 get_specular_color() +virtual vec3 get_specular_color() { if(use_specular_map) return texture(specular_map, texcoord.xy).rgb; @@ -30,7 +30,7 @@ vec3 get_specular_color() return basic_material.specular.rgb; } -float get_shininess_value() +virtual float get_shininess_value() { if(use_shininess_map) return texture(shininess_map, texcoord.xy).r*255.0; @@ -38,7 +38,7 @@ float get_shininess_value() return basic_material.shininess; } -vec3 get_emission_color() +virtual vec3 get_emission_color() { if(use_emission_map) return texture(emission_map, texcoord.xy).rgb; @@ -46,7 +46,7 @@ vec3 get_emission_color() return basic_material.emission.rgb; } -float get_reflectivity_value() +virtual float get_reflectivity_value() { if(use_reflectivity_map) return texture(reflectivity_map, texcoord.xy).r; diff --git a/shaderlib/shadow.glsl b/shaderlib/shadow.glsl index d751b460..6f4acd27 100644 --- a/shaderlib/shadow.glsl +++ b/shaderlib/shadow.glsl @@ -9,7 +9,7 @@ void shadow_transform(vec4 eye_vertex) } #pragma MSP stage(fragment) -float get_shadow_factor(int index) +virtual float get_shadow_factor(int index) { if(use_shadow_map) { diff --git a/source/glsl/generate.cpp b/source/glsl/generate.cpp index c670bc1a..2ff75194 100644 --- a/source/glsl/generate.cpp +++ b/source/glsl/generate.cpp @@ -986,6 +986,15 @@ void FunctionResolver::visit(FunctionDeclaration &func) vector &decls = declarations[key]; if(func.definition==&func) { + if(stage_decl && stage_decl->definition) + { + if(!func.overrd) + stage->diagnostics.push_back(Diagnostic(Diagnostic::WARN, func.source, func.line, + format("Overriding function '%s' without the override keyword is deprecated", key))); + if(!stage_decl->definition->virtua) + stage->diagnostics.push_back(Diagnostic(Diagnostic::WARN, func.source, func.line, + format("Overriding function '%s' not declared as virtual is deprecated", key))); + } stage_decl = &func; // Set all previous declarations to use this definition. diff --git a/source/glsl/parser.cpp b/source/glsl/parser.cpp index 0c3a5e35..31f9fcb6 100644 --- a/source/glsl/parser.cpp +++ b/source/glsl/parser.cpp @@ -294,6 +294,8 @@ RefPtr Parser::parse_global_declaration() } else if(is_qualifier(token)) return parse_variable_declaration(); + else if(token=="virtual") + return parse_function_declaration(); else if(is_type(token)) { if(tokenizer.peek_token(2)=="(") @@ -750,6 +752,7 @@ RefPtr Parser::parse_function_declaration() { RefPtr func = create_node(); + func->virtua = check("virtual"); func->return_type = expect_type(); func->name = expect_identifier(); tokenizer.expect("("); @@ -768,6 +771,8 @@ RefPtr Parser::parse_function_declaration() } tokenizer.expect(")"); + func->overrd = check("override"); + string token = tokenizer.peek_token(); if(token=="{") { diff --git a/source/glsl/syntax.cpp b/source/glsl/syntax.cpp index 11a099b5..025af271 100644 --- a/source/glsl/syntax.cpp +++ b/source/glsl/syntax.cpp @@ -400,6 +400,8 @@ void InterfaceBlock::visit(NodeVisitor &visitor) FunctionDeclaration::FunctionDeclaration(): + virtua(false), + overrd(false), definition(0), return_type_declaration(0) { } @@ -409,6 +411,8 @@ FunctionDeclaration::FunctionDeclaration(const FunctionDeclaration &other): return_type(other.return_type), name(other.name), parameters(other.parameters), + virtua(other.virtua), + overrd(other.overrd), body(other.body), signature(other.signature), definition(other.definition==&other ? this : 0), diff --git a/source/glsl/syntax.h b/source/glsl/syntax.h index 86972869..81fd6b4f 100644 --- a/source/glsl/syntax.h +++ b/source/glsl/syntax.h @@ -458,6 +458,8 @@ struct FunctionDeclaration: Statement std::string return_type; std::string name; NodeArray parameters; + bool virtua; + bool overrd; Block body; std::string signature; diff --git a/tests/glsl/function_override.glsl b/tests/glsl/function_override.glsl new file mode 100644 index 00000000..c7e64d52 --- /dev/null +++ b/tests/glsl/function_override.glsl @@ -0,0 +1,22 @@ +#pragma MSP stage(vertex) +layout(location=0) in vec4 position; +virtual float get_scale() +{ + return 1.0; +} +int main() +{ + gl_Position = position*get_scale(); +} +float get_scale() override +{ + return 2.0; +} + +/* Expected output: vertex +layout(location=0) in vec4 position; +int main() +{ + gl_Position = position*2.0; +} +*/ -- 2.45.2