]> git.tdb.fi Git - libs/gl.git/commitdiff
Handle depth range conversion in geometry and tessellation shaders
authorMikko Rasa <tdb@tdb.fi>
Mon, 10 Oct 2022 11:49:11 +0000 (14:49 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 10 Oct 2022 13:17:04 +0000 (16:17 +0300)
Clip coordinates are taken from the last stage to deal with vertex
positions, so always converting in the vertex shader is not appropriate.
A geometry shader needs the conversion before every EmitVertex call.

source/glsl/compiler.cpp
source/glsl/finalize.cpp
source/glsl/finalize.h
source/glsl/syntax.h

index 97c234f79285f3c253e94d76dd36b937d13e55b4..a717a9278be25be85066603bab71c9fd52422d49 100644 (file)
@@ -94,10 +94,7 @@ void Compiler::compile(Mode mode)
                        ConstantSpecializer().apply(s, spec_values);
        }
        if(mode==PROGRAM)
-       {
-               for(Stage &s: module->stages)
-                       DepthRangeConverter().apply(s, features);
-       }
+               DepthRangeConverter().apply(*module, features);
        for(auto i=module->stages.begin(); i!=module->stages.end(); )
        {
                OptimizeResult result = optimize(*i);
index e4d61ad13d87719bab032874c744ca6a7e959b59..91d2e44c52560fd6ff5fde842e9ef1d3d9f29076 100644 (file)
@@ -252,12 +252,13 @@ void LocationAllocator::visit(VariableDeclaration &var)
 }
 
 
-void DepthRangeConverter::apply(Stage &stage, const Features &features)
+void DepthRangeConverter::apply(Module &module, const Features &features)
 {
-       if(stage.type!=Stage::VERTEX || features.target_api==VULKAN)
+       if(features.target_api==VULKAN)
                return;
 
-       stage.content.visit(*this);
+       for(Stage *s=&module.stages.back(); (!r_position_z_assigned && s); s=s->previous)
+               s->content.visit(*this);
 }
 
 NodePtr<Statement> DepthRangeConverter::create_conversion_statement()
@@ -298,6 +299,20 @@ NodePtr<Statement> DepthRangeConverter::create_conversion_statement()
        return statement;
 }
 
+void DepthRangeConverter::visit(Block &block)
+{
+       for(auto i=block.body.begin(); i!=block.body.end(); ++i)
+       {
+               r_emitvertex = false;
+               (*i)->visit(*this);
+               if(r_emitvertex && !r_position_z_assigned)
+               {
+                       block.body.insert_nocopy(i, create_conversion_statement());
+                       r_position_z_assigned = true;
+               }
+       }
+}
+
 void DepthRangeConverter::visit(VariableReference &var)
 {
        const StructDeclaration *strct = dynamic_cast<const StructDeclaration *>(var.type);
@@ -309,6 +324,11 @@ void DepthRangeConverter::visit(MemberAccess &memacc)
        r_gl_pervertex = false;
        memacc.left->visit(*this);
        r_gl_position = (r_gl_pervertex && memacc.member=="gl_Position");
+       if(assignment_target && r_gl_position)
+       {
+               r_position_assigned = true;
+               r_position_z_assigned = false;
+       }
 }
 
 void DepthRangeConverter::visit(Swizzle &swiz)
@@ -328,13 +348,22 @@ void DepthRangeConverter::visit(Assignment &assign)
        assign.right->visit(*this);
 }
 
+void DepthRangeConverter::visit(FunctionCall &call)
+{
+       if(call.name=="EmitVertex")
+               r_emitvertex = true;
+}
+
 void DepthRangeConverter::visit(FunctionDeclaration &func)
 {
        r_position_z_assigned = false;
        TraversingVisitor::visit(func);
 
-       if(func.definition==&func && func.name=="main" && !r_position_z_assigned)
+       if(func.definition==&func && func.name=="main" && r_position_assigned && !r_position_z_assigned)
+       {
                func.body.body.push_back_nocopy(create_conversion_statement());
+               r_position_z_assigned = true;
+       }
 }
 
 
index 510f3987010e9488071c1e0702bdcf647c360639..7b47e8ec5a24aa492218e32036f61f065a5d68e1 100644 (file)
@@ -69,18 +69,22 @@ private:
        bool assignment_target = false;
        bool r_gl_pervertex = false;
        bool r_gl_position = false;
+       bool r_emitvertex = false;
+       bool r_position_assigned = false;
        bool r_position_z_assigned = false;
 
 public:
-       void apply(Stage &, const Features &);
+       void apply(Module &, const Features &);
 
 private:
        NodePtr<Statement> create_conversion_statement();
 
+       virtual void visit(Block &);
        virtual void visit(VariableReference &);
        virtual void visit(MemberAccess &);
        virtual void visit(Swizzle &);
        virtual void visit(Assignment &);
+       virtual void visit(FunctionCall &);
        virtual void visit(FunctionDeclaration &);
 };
 
index ebe188e1f6afa932fe5fd697509c043cfeb5ef23..1aa56cb708a05da8e1be7d379b5603a6e4edbf51 100644 (file)
@@ -99,6 +99,9 @@ public:
 
        void push_back_nocopy(const typename C::value_type &v)
        { C::push_back(0); C::back() = v; }
+
+       void insert_nocopy(typename C::iterator i, const typename C::value_type &v)
+       { i = C::insert(i, 0); *i = v; }
 };
 
 template<typename T>