From: Mikko Rasa Date: Mon, 10 Oct 2022 11:49:11 +0000 (+0300) Subject: Handle depth range conversion in geometry and tessellation shaders X-Git-Url: https://git.tdb.fi/?a=commitdiff_plain;h=124ccebc731b2f58e0f7a5a8bc6f40a01fa55f49;p=libs%2Fgl.git Handle depth range conversion in geometry and tessellation shaders 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. --- diff --git a/source/glsl/compiler.cpp b/source/glsl/compiler.cpp index 97c234f7..a717a927 100644 --- a/source/glsl/compiler.cpp +++ b/source/glsl/compiler.cpp @@ -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); diff --git a/source/glsl/finalize.cpp b/source/glsl/finalize.cpp index e4d61ad1..91d2e44c 100644 --- a/source/glsl/finalize.cpp +++ b/source/glsl/finalize.cpp @@ -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 DepthRangeConverter::create_conversion_statement() @@ -298,6 +299,20 @@ NodePtr 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(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; + } } diff --git a/source/glsl/finalize.h b/source/glsl/finalize.h index 510f3987..7b47e8ec 100644 --- a/source/glsl/finalize.h +++ b/source/glsl/finalize.h @@ -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 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 &); }; diff --git a/source/glsl/syntax.h b/source/glsl/syntax.h index ebe188e1..1aa56cb7 100644 --- a/source/glsl/syntax.h +++ b/source/glsl/syntax.h @@ -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