Skip to content

Commit c062b6b

Browse files
Merge pull request #1725 from billhollings/fix-duplicate-glposition
MSL: Fix duplicate gl_Position outputs when gl_Position defined but unused.
2 parents fad1590 + 3105e82 commit c062b6b

4 files changed

Lines changed: 76 additions & 3 deletions

File tree

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <metal_stdlib>
2+
#include <simd/simd.h>
3+
4+
using namespace metal;
5+
6+
struct main0_out
7+
{
8+
float4 gl_Position [[position]];
9+
float gl_PointSize [[point_size]];
10+
};
11+
12+
vertex main0_out main0()
13+
{
14+
main0_out out = {};
15+
out.gl_PointSize = 1.0;
16+
return out;
17+
}
18+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <metal_stdlib>
2+
#include <simd/simd.h>
3+
4+
using namespace metal;
5+
6+
struct main0_out
7+
{
8+
float4 gl_Position [[position]];
9+
float gl_PointSize [[point_size]];
10+
};
11+
12+
vertex main0_out main0()
13+
{
14+
main0_out out = {};
15+
out.gl_PointSize = 1.0;
16+
return out;
17+
}
18+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#version 450
2+
3+
out gl_PerVertex
4+
{
5+
vec4 gl_Position;
6+
float gl_PointSize;
7+
float gl_ClipDistance[1];
8+
};
9+
10+
void main()
11+
{
12+
gl_PointSize = 1.0;
13+
}

spirv_msl.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -877,12 +877,36 @@ void CompilerMSL::build_implicit_builtins()
877877
if (need_position)
878878
{
879879
// If we can get away with returning void from entry point, we don't need to care.
880-
// If there is at least one other stage output, we need to return [[position]].
881-
need_position = false;
880+
// If there is at least one other stage output, we need to return [[position]],
881+
// so we need to create one if it doesn't appear in the SPIR-V. Before adding the
882+
// implicit variable, check if it actually exists already, but just has not been used
883+
// or initialized, and if so, mark it as active, and do not create the implicit variable.
884+
bool has_output = false;
882885
ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
883886
if (var.storage == StorageClassOutput && interface_variable_exists_in_entry_point(var.self))
884-
need_position = true;
887+
{
888+
has_output = true;
889+
890+
// Check if the var is the Position builtin
891+
if (has_decoration(var.self, DecorationBuiltIn) && get_decoration(var.self, DecorationBuiltIn) == BuiltInPosition)
892+
active_output_builtins.set(BuiltInPosition);
893+
894+
// If the var is a struct, check if any members is the Position builtin
895+
auto &var_type = get_variable_element_type(var);
896+
if (var_type.basetype == SPIRType::Struct)
897+
{
898+
auto mbr_cnt = var_type.member_types.size();
899+
for (uint32_t mbr_idx = 0; mbr_idx < mbr_cnt; mbr_idx++)
900+
{
901+
auto builtin = BuiltInMax;
902+
bool is_builtin = is_member_builtin(var_type, mbr_idx, &builtin);
903+
if (is_builtin && builtin == BuiltInPosition)
904+
active_output_builtins.set(BuiltInPosition);
905+
}
906+
}
907+
}
885908
});
909+
need_position = has_output && !active_output_builtins.get(BuiltInPosition);
886910
}
887911

888912
if (need_position)

0 commit comments

Comments
 (0)