From 124ccebc731b2f58e0f7a5a8bc6f40a01fa55f49 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 10 Oct 2022 14:49:11 +0300 Subject: [PATCH] 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. --- source/glsl/compiler.cpp | 5 +---- source/glsl/finalize.cpp | 37 +++++++++++++++++++++++++++++++++---- source/glsl/finalize.h | 6 +++++- source/glsl/syntax.h | 3 +++ 4 files changed, 42 insertions(+), 9 deletions(-) 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 -- 2.45.2