Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/KhronosGroup/SPIRV-Cross.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Hollings <bill.hollings@brenwill.com>2021-08-16 18:23:15 +0300
committerBill Hollings <bill.hollings@brenwill.com>2021-08-16 18:23:15 +0300
commit3105e82b2e14832b5d4027467e5894e2d70cb0d1 (patch)
treeae684f5f845316e8b932f45d0d79cbe468cec643
parentbab4e5911b1bfa5a86bc80006b7301ae48363844 (diff)
MSL: Fix duplicate gl_Position outputs when gl_Position defined but unused.
When gl_Position is defined by SPIR-V, but neither used nor initialized, it appeared twice in the MSL output, as gl_Position and glPosition_1. The existing tests for whether an output is active check only that it is used by an op, or initialized. Adding the implicit gl_Position also marked the existing gl_Position as active, duplicating the output variable. Fix is that when checking for the need to add an implicit gl_Position output, also check if the var is already defined in the shader, and just needs to be marked as active. Add test shader.
-rw-r--r--reference/opt/shaders-msl/vert/unused-position.vert18
-rw-r--r--reference/shaders-msl/vert/unused-position.vert18
-rw-r--r--shaders-msl/vert/unused-position.vert13
-rw-r--r--spirv_msl.cpp30
4 files changed, 76 insertions, 3 deletions
diff --git a/reference/opt/shaders-msl/vert/unused-position.vert b/reference/opt/shaders-msl/vert/unused-position.vert
new file mode 100644
index 00000000..7dc46721
--- /dev/null
+++ b/reference/opt/shaders-msl/vert/unused-position.vert
@@ -0,0 +1,18 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+ float4 gl_Position [[position]];
+ float gl_PointSize [[point_size]];
+};
+
+vertex main0_out main0()
+{
+ main0_out out = {};
+ out.gl_PointSize = 1.0;
+ return out;
+}
+
diff --git a/reference/shaders-msl/vert/unused-position.vert b/reference/shaders-msl/vert/unused-position.vert
new file mode 100644
index 00000000..7dc46721
--- /dev/null
+++ b/reference/shaders-msl/vert/unused-position.vert
@@ -0,0 +1,18 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+
+using namespace metal;
+
+struct main0_out
+{
+ float4 gl_Position [[position]];
+ float gl_PointSize [[point_size]];
+};
+
+vertex main0_out main0()
+{
+ main0_out out = {};
+ out.gl_PointSize = 1.0;
+ return out;
+}
+
diff --git a/shaders-msl/vert/unused-position.vert b/shaders-msl/vert/unused-position.vert
new file mode 100644
index 00000000..61e30b43
--- /dev/null
+++ b/shaders-msl/vert/unused-position.vert
@@ -0,0 +1,13 @@
+#version 450
+
+out gl_PerVertex
+{
+ vec4 gl_Position;
+ float gl_PointSize;
+ float gl_ClipDistance[1];
+};
+
+void main()
+{
+ gl_PointSize = 1.0;
+}
diff --git a/spirv_msl.cpp b/spirv_msl.cpp
index 76c55652..8fbe7e3a 100644
--- a/spirv_msl.cpp
+++ b/spirv_msl.cpp
@@ -877,12 +877,36 @@ void CompilerMSL::build_implicit_builtins()
if (need_position)
{
// If we can get away with returning void from entry point, we don't need to care.
- // If there is at least one other stage output, we need to return [[position]].
- need_position = false;
+ // If there is at least one other stage output, we need to return [[position]],
+ // so we need to create one if it doesn't appear in the SPIR-V. Before adding the
+ // implicit variable, check if it actually exists already, but just has not been used
+ // or initialized, and if so, mark it as active, and do not create the implicit variable.
+ bool has_output = false;
ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
if (var.storage == StorageClassOutput && interface_variable_exists_in_entry_point(var.self))
- need_position = true;
+ {
+ has_output = true;
+
+ // Check if the var is the Position builtin
+ if (has_decoration(var.self, DecorationBuiltIn) && get_decoration(var.self, DecorationBuiltIn) == BuiltInPosition)
+ active_output_builtins.set(BuiltInPosition);
+
+ // If the var is a struct, check if any members is the Position builtin
+ auto &var_type = get_variable_element_type(var);
+ if (var_type.basetype == SPIRType::Struct)
+ {
+ auto mbr_cnt = var_type.member_types.size();
+ for (uint32_t mbr_idx = 0; mbr_idx < mbr_cnt; mbr_idx++)
+ {
+ auto builtin = BuiltInMax;
+ bool is_builtin = is_member_builtin(var_type, mbr_idx, &builtin);
+ if (is_builtin && builtin == BuiltInPosition)
+ active_output_builtins.set(BuiltInPosition);
+ }
+ }
+ }
});
+ need_position = has_output && !active_output_builtins.get(BuiltInPosition);
}
if (need_position)