SpirvShader: Consider OpEntryPoint interface IDs
Bug: swiftshader:161
Change-Id: Ib26cb1f6edb2549fc42420e7cc1579ce4ae36952
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/55148
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index f82f1e8..58c7ca5 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -61,8 +61,8 @@
}
}
- // Simplifying assumptions (to be satisfied by earlier transformations)
- // - The only input/output OpVariables present are those used by the entrypoint
+ // The identifiers of all OpVariables that define the entry point's IO variables.
+ std::unordered_set<Object::ID> interfaceIds;
Function::ID currentFunction;
Block::ID currentBlock;
@@ -84,6 +84,12 @@
{
ASSERT_MSG(entryPoint == 0, "Duplicate entry point with name '%s' and stage %d", name, int(stage));
entryPoint = id;
+
+ auto interfaceIdsOffset = 3 + insn.stringSizeInWords(3);
+ for(uint32_t i = interfaceIdsOffset; i < insn.wordCount(); i++)
+ {
+ interfaceIds.emplace(insn.word(i));
+ }
}
}
break;
@@ -271,7 +277,10 @@
{
case spv::StorageClassInput:
case spv::StorageClassOutput:
- ProcessInterfaceVariable(object);
+ if(interfaceIds.count(resultId))
+ {
+ ProcessInterfaceVariable(object);
+ }
break;
case spv::StorageClassUniform:
diff --git a/src/Pipeline/SpirvShader.hpp b/src/Pipeline/SpirvShader.hpp
index da9cf63..900199b 100644
--- a/src/Pipeline/SpirvShader.hpp
+++ b/src/Pipeline/SpirvShader.hpp
@@ -204,6 +204,35 @@
return reinterpret_cast<const char *>(wordPointer(n));
}
+ // Returns the number of whole-words that a string literal starting at
+ // word n consumes. If the end of the intruction is reached before the
+ // null-terminator is found, then the function DABORT()s and 0 is
+ // returned.
+ uint32_t stringSizeInWords(uint32_t n) const
+ {
+ uint32_t c = wordCount();
+ for(uint32_t i = n; n < c; i++)
+ {
+ auto *u32 = wordPointer(i);
+ auto *u8 = reinterpret_cast<const uint8_t *>(u32);
+ // SPIR-V spec 2.2.1. Instructions:
+ // A string is interpreted as a nul-terminated stream of
+ // characters. The character set is Unicode in the UTF-8
+ // encoding scheme. The UTF-8 octets (8-bit bytes) are packed
+ // four per word, following the little-endian convention (i.e.,
+ // the first octet is in the lowest-order 8 bits of the word).
+ // The final word contains the string’s nul-termination
+ // character (0), and all contents past the end of the string in
+ // the final word are padded with 0.
+ if(u8[3] == 0)
+ {
+ return 1 + i - n;
+ }
+ }
+ DABORT("SPIR-V string literal was not null-terminated");
+ return 0;
+ }
+
bool hasResultAndType() const
{
bool hasResult = false, hasResultType = false;