Allow repeated params in Metal out-params helper.
The out-param helpers emitted by the Metal code gen (intended to provide
GLSL out-parameter semantics in Metal) emitted bad code if passed the
same variable for two separate out parameters. It would previously
create two parameters in the helper with the same name. The helper
function now omits the name of the second variable in the parameter list
if it is redundant; we already know the caller is passing the same
variable twice.
Change-Id: Ibdc6c02a9e9e4bdb4f4546a25068f2018aa07b10
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/370258
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/sksl/SkSLMetalCodeGenerator.cpp b/src/sksl/SkSLMetalCodeGenerator.cpp
index 8b58453..88666b3 100644
--- a/src/sksl/SkSLMetalCodeGenerator.cpp
+++ b/src/sksl/SkSLMetalCodeGenerator.cpp
@@ -232,6 +232,11 @@
SkASSERT(outVars.size() == arguments.size());
SkASSERT(outVars.size() == function.parameters().size());
+ // We need to detect cases where the caller passes the same variable as an out-param more than
+ // once, and avoid reusing the variable name. (In those cases we can actually just ignore the
+ // redundant input parameter entirely, and not give it any name.)
+ std::unordered_set<const Variable*> writtenVars;
+
for (int index = 0; index < arguments.count(); ++index) {
this->write(separator);
separator = ", ";
@@ -246,10 +251,13 @@
this->write("&");
}
if (outVars[index]) {
- this->write(" ");
- fIgnoreVariableReferenceModifiers = true;
- this->writeVariableReference(*outVars[index]);
- fIgnoreVariableReferenceModifiers = false;
+ auto [iter, didInsert] = writtenVars.insert(outVars[index]->variable());
+ if (didInsert) {
+ this->write(" ");
+ fIgnoreVariableReferenceModifiers = true;
+ this->writeVariableReference(*outVars[index]);
+ fIgnoreVariableReferenceModifiers = false;
+ }
} else {
this->write(" _var");
this->write(to_string(index));