r_ternary_result = 0;
}
+void ConstantConditionEliminator::visit(UnaryExpression &unary)
+{
+ if(unary.oper->token[1]=='+' || unary.oper->token[1]=='-')
+ if(const VariableReference *var = dynamic_cast<const VariableReference *>(unary.expression.get()))
+ {
+ auto i = current_block->variables.find(var->name);
+ r_external_side_effects = (i==current_block->variables.end() || i->second!=var->declaration);
+ return;
+ }
+
+ TraversingVisitor::visit(unary);
+}
+
+void ConstantConditionEliminator::visit(Assignment &assign)
+{
+ auto i = find_if(current_block->variables, [&assign](const pair<string, VariableDeclaration *> &kvp){ return kvp.second==assign.target.declaration; });
+ if(i==current_block->variables.end())
+ r_external_side_effects = true;
+ TraversingVisitor::visit(assign);
+}
+
void ConstantConditionEliminator::visit(TernaryExpression &ternary)
{
ConstantStatus result = check_constant_condition(*ternary.condition);
r_ternary_result = 0;
}
+void ConstantConditionEliminator::visit(FunctionCall &call)
+{
+ r_external_side_effects = true;
+ TraversingVisitor::visit(call);
+}
+
void ConstantConditionEliminator::visit(Conditional &cond)
{
ConstantStatus result = check_constant_condition(*cond.condition);
return;
}
+ r_external_side_effects = false;
TraversingVisitor::visit(cond);
+
+ if(cond.body.body.empty() && cond.else_body.body.empty() && !r_external_side_effects)
+ nodes_to_remove.insert(&cond);
}
void ConstantConditionEliminator::visit(Iteration &iter)
}
}
+ r_external_side_effects = false;
TraversingVisitor::visit(iter);
+ if(iter.body.body.empty() && !r_external_side_effects)
+ nodes_to_remove.insert(&iter);
}
};
/** Removes conditional statements and loops where the condition can be
-determined as constant at compile time. */
+determined as constant at compile time. Also removes such statements where
+the body is empty and the condition has no side effects. */
class ConstantConditionEliminator: private TraversingVisitor
{
private:
NodeList<Statement>::iterator insert_point;
std::set<Node *> nodes_to_remove;
RefPtr<Expression> r_ternary_result;
+ bool r_external_side_effects;
public:
void apply(Stage &);
virtual void visit(Block &);
virtual void visit(RefPtr<Expression> &);
+ virtual void visit(UnaryExpression &);
+ virtual void visit(Assignment &);
virtual void visit(TernaryExpression &);
+ virtual void visit(FunctionCall &);
virtual void visit(Conditional &);
virtual void visit(Iteration &);
};
--- /dev/null
+uniform Lighting
+{
+ vec3 light_dir;
+ mat4 shadow_matrix;
+ int shadow_enabled;
+};
+uniform Transform
+{
+ mat4 vp;
+ mat4 model;
+};
+uniform sampler2DShadow shadow_map;
+const bool use_light = false;
+
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 vertex;
+layout(location=1) in vec3 normal;
+void main()
+{
+ vec4 world_vertex = model*vertex;
+ out vec3 world_normal = mat3(model)*normal;
+ gl_Position = vp*world_vertex;
+ if(shadow_enabled!=0)
+ {
+ out vec3 shadow_coord = (shadow_matrix*world_vertex).xyz;
+ }
+}
+
+#pragma MSP stage(fragment)
+layout(location=0) out vec4 frag_color;
+void main()
+{
+ vec3 color = vec3(1.0);
+ if(use_light)
+ {
+ float intensity = max(dot(normalize(world_normal), light_dir), 0.0);
+ if(shadow_enabled!=0)
+ intensity *= texture(shadow_map, shadow_coord);
+ color *= intensity;
+ }
+ frag_color = vec4(color, 1.0);
+}
+
+/* Expected output: vertex
+layout(binding=48) uniform Transform
+{
+ mat4 vp;
+ mat4 model;
+};
+layout(location=0) in vec4 vertex;
+void main()
+{
+ gl_Position = vp*model*vertex;
+}
+*/
+
+/* Expected output: fragment
+layout(location=0) out vec4 frag_color;
+void main()
+{
+ frag_color = vec4(vec3(1.0), 1.0);
+}
+*/
--- /dev/null
+uniform Lighting
+{
+ vec4 light_dir[2];
+};
+uniform Transform
+{
+ mat4 vp;
+ mat4 model;
+};
+const bool use_light = false;
+
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 vertex;
+layout(location=1) in vec3 normal;
+out vec3 world_light_dir[2];
+void main()
+{
+ vec4 world_vertex = model*vertex;
+ out vec3 world_normal = mat3(model)*normal;
+ gl_Position = vp*world_vertex;
+ for(int i=0; i<2; ++i)
+ world_light_dir[i] = light_dir[i].xyz-world_vertex.xyz*light_dir[i].w;
+}
+
+#pragma MSP stage(fragment)
+layout(location=0) out vec4 frag_color;
+void main()
+{
+ vec3 color = vec3(0.1);
+ if(use_light)
+ {
+ for(int i=0; i<2; ++i)
+ {
+ float intensity = max(dot(normalize(world_normal), world_light_dir[i]), 0.0);
+ color += intensity;
+ }
+ }
+ frag_color = vec4(color, 1.0);
+}
+
+/* Expected output: vertex
+layout(binding=48) uniform Transform
+{
+ mat4 vp;
+ mat4 model;
+};
+layout(location=0) in vec4 vertex;
+void main()
+{
+ gl_Position = vp*model*vertex;
+}
+*/
+
+/* Expected output: fragment
+layout(location=0) out vec4 frag_color;
+void main()
+{
+ frag_color = vec4(vec3(0.1), 1.0);
+}
+*/
--- /dev/null
+uniform sampler2D tex;
+
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 vertex;
+layout(location=1) in vec2 texcoord;
+void main()
+{
+ gl_Position = vertex;
+ passthrough;
+}
+
+#pragma MSP stage(fragment)
+layout(location=0) out float result;
+void main()
+{
+ float value = texture(tex, texcoord).r;
+ float pot;
+ for(pot=0; pot<value; pot*=2) { }
+ result = pot;
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 vertex;
+layout(location=1) in vec2 texcoord;
+layout(location=0) out vec2 _vs_out_texcoord;
+void main()
+{
+ gl_Position = vertex;
+ _vs_out_texcoord = texcoord;
+}
+*/
+
+/* Expected output: fragment
+layout(location=0, binding=71) uniform sampler2D tex;
+layout(location=0) out float result;
+layout(location=0) in vec2 _vs_out_texcoord;
+void main()
+{
+ float value = texture(tex, _vs_out_texcoord).r;
+ float pot;
+ for(pot = 0.0; pot<value; pot *= 2.0) { }
+ result = pot;
+}
+*/