diff options
author | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2024-11-22 15:07:17 -0600 |
---|---|---|
committer | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2024-11-29 04:55:32 -0600 |
commit | 72699bd7edad7dd007ebfa74a19881537f0e9cc0 (patch) | |
tree | bfe51a0d6522b90b98864e97819f2ea291cb09a4 | |
parent | f41957bedabd2290eeb23af57c1775a6671fb1d1 (diff) | |
download | packages-72699bd7edad7dd007ebfa74a19881537f0e9cc0.tar.gz packages-72699bd7edad7dd007ebfa74a19881537f0e9cc0.tar.bz2 packages-72699bd7edad7dd007ebfa74a19881537f0e9cc0.tar.xz packages-72699bd7edad7dd007ebfa74a19881537f0e9cc0.zip |
user/spirv-tools: Patch for cross-endian shaders
This integrates a patch that is currently sitting upstream in review.
Adding this patch corrects the tools to work on cross-endian binaries,
i.e. a big-endian system can handle little-endian shaders, and vis versa.
See-also: https://github.com/KhronosGroup/SPIRV-Tools/issues/5595
-rw-r--r-- | user/spirv-tools/APKBUILD | 5 | ||||
-rw-r--r-- | user/spirv-tools/endian.patch | 283 |
2 files changed, 287 insertions, 1 deletions
diff --git a/user/spirv-tools/APKBUILD b/user/spirv-tools/APKBUILD index b98a68a43..874d2de0a 100644 --- a/user/spirv-tools/APKBUILD +++ b/user/spirv-tools/APKBUILD @@ -12,7 +12,9 @@ depends_dev="spirv-headers" makedepends="$depends_dev cmake python3" subpackages="$pkgname-dev" source="spirv-tools-$pkgver.tar.gz::https://github.com/KhronosGroup/SPIRV-Tools/archive/refs/tags/v$pkgver.tar.gz - remove-copyright-check-test.patch" + endian.patch + remove-copyright-check-test.patch + " builddir="$srcdir/SPIRV-Tools-$pkgver" build() { @@ -42,4 +44,5 @@ package() { } sha512sums="804e2a076025a9afde2d7b0b6950fa7b7289b9aa911348b10aad45cc3515116b7484e886d49b524315f75e8d1a2009c2f26310352c154d1b23a58864e8535324 spirv-tools-2024.3.tar.gz +d31f1650a9f1d35b4ee95eddd6bd6aceb3490591e269f283b71589cfd3ca69b77467cabf659fdc42ee96433092434137a3be55c69b60b7edbcc40d5ed76357b1 endian.patch a04f1a4d60d6206cbbd5e97dda58ca05689835520617dfe7bdfe29d66ab987f68080fbee85c039aecab554e01d94b16a99acfc2ffd29d9ef5861d3dd2e2dccb1 remove-copyright-check-test.patch" diff --git a/user/spirv-tools/endian.patch b/user/spirv-tools/endian.patch new file mode 100644 index 000000000..82a2812ad --- /dev/null +++ b/user/spirv-tools/endian.patch @@ -0,0 +1,283 @@ +From 4826b6eabc6102e49562c48effcabb7b87ceb041 Mon Sep 17 00:00:00 2001 +From: Hugo Devillers <hugo@xol.io> +Date: Sat, 1 Jul 2023 11:33:17 +0200 +Subject: [PATCH 1/6] remove dead code dealing with operand endianness + +--- + source/binary.cpp | 21 ++++++--------------- + 1 file changed, 6 insertions(+), 15 deletions(-) + +diff --git a/source/binary.cpp b/source/binary.cpp +index 207d4a9b37..b1e1922445 100644 +--- a/source/binary.cpp ++++ b/source/binary.cpp +@@ -440,10 +440,6 @@ spv_result_t Parser::parseOperand(size_t inst_offset, + + const uint32_t word = peek(); + +- // Do the words in this operand have to be converted to native endianness? +- // True for all but literal strings. +- bool convert_operand_endianness = true; +- + switch (type) { + case SPV_OPERAND_TYPE_TYPE_ID: + if (!word) +@@ -752,17 +748,12 @@ spv_result_t Parser::parseOperand(size_t inst_offset, + + if (_.requires_endian_conversion) { + // Copy instruction words. Translate to native endianness as needed. +- if (convert_operand_endianness) { +- const spv_endianness_t endianness = _.endian; +- std::transform(_.words + _.word_index, _.words + index_after_operand, +- std::back_inserter(*words), +- [endianness](const uint32_t raw_word) { +- return spvFixWord(raw_word, endianness); +- }); +- } else { +- words->insert(words->end(), _.words + _.word_index, +- _.words + index_after_operand); +- } ++ const spv_endianness_t endianness = _.endian; ++ std::transform(_.words + _.word_index, _.words + index_after_operand, ++ std::back_inserter(*words), ++ [endianness](const uint32_t raw_word) { ++ return spvFixWord(raw_word, endianness); ++ }); + } + + // Advance past the operand. + +From 39a63f822f0d1d93cabba4f4f3d980bc6ec1737b Mon Sep 17 00:00:00 2001 +From: Hugo Devillers <hugo@xol.io> +Date: Sat, 1 Jul 2023 11:50:03 +0200 +Subject: [PATCH 2/6] perform endianness conversion eagerly + +--- + source/binary.cpp | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/source/binary.cpp b/source/binary.cpp +index b1e1922445..d46dbc1d9e 100644 +--- a/source/binary.cpp ++++ b/source/binary.cpp +@@ -207,6 +207,10 @@ class Parser { + operands.reserve(25); + endian_converted_words.reserve(25); + expected_operands.reserve(25); ++ ++ native_words = std::make_unique<uint32_t[]>(num_words); ++ for (size_t i = 0; i < num_words; i++) ++ native_words[i] = spvFixWord(words[i], endian); + } + State() : State(0, 0, nullptr) {} + const uint32_t* words; // Words in the binary SPIR-V module. +@@ -218,6 +222,7 @@ class Parser { + // Is the SPIR-V binary in a different endianness from the host native + // endianness? + bool requires_endian_conversion; ++ std::unique_ptr<uint32_t[]> native_words; + + // Maps a result ID to its type ID. By convention: + // - a result ID that is a type definition maps to itself. +@@ -748,12 +753,8 @@ spv_result_t Parser::parseOperand(size_t inst_offset, + + if (_.requires_endian_conversion) { + // Copy instruction words. Translate to native endianness as needed. +- const spv_endianness_t endianness = _.endian; +- std::transform(_.words + _.word_index, _.words + index_after_operand, +- std::back_inserter(*words), +- [endianness](const uint32_t raw_word) { +- return spvFixWord(raw_word, endianness); +- }); ++ words->insert(words->end(), _.native_words.get() + _.word_index, ++ _.native_words.get() + index_after_operand); + } + + // Advance past the operand. + +From e6005633e64f4dac33aa2c4de42fe6bd3fb648ca Mon Sep 17 00:00:00 2001 +From: Hugo Devillers <hugo@xol.io> +Date: Sat, 1 Jul 2023 11:51:37 +0200 +Subject: [PATCH 3/6] fix string literals when file has non-native endianness + +--- + source/binary.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source/binary.cpp b/source/binary.cpp +index d46dbc1d9e..34cb608abe 100644 +--- a/source/binary.cpp ++++ b/source/binary.cpp +@@ -591,7 +591,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset, + case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING: { + const size_t max_words = _.num_words - _.word_index; + std::string string = +- spvtools::utils::MakeString(_.words + _.word_index, max_words, false); ++ spvtools::utils::MakeString(_.native_words.get() + _.word_index, max_words, false); + + if (string.length() == max_words * 4) + return exhaustedInputDiagnostic(inst_offset, opcode, type); + +From 3ccc744e814609fe63b755e37240e03cf07e2f2b Mon Sep 17 00:00:00 2001 +From: Hugo Devillers <hugo@xol.io> +Date: Sat, 1 Jul 2023 12:24:16 +0200 +Subject: [PATCH 4/6] don't convert endianness if not required + +--- + source/binary.cpp | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/source/binary.cpp b/source/binary.cpp +index 34cb608abe..69bd082598 100644 +--- a/source/binary.cpp ++++ b/source/binary.cpp +@@ -207,10 +207,6 @@ class Parser { + operands.reserve(25); + endian_converted_words.reserve(25); + expected_operands.reserve(25); +- +- native_words = std::make_unique<uint32_t[]>(num_words); +- for (size_t i = 0; i < num_words; i++) +- native_words[i] = spvFixWord(words[i], endian); + } + State() : State(0, 0, nullptr) {} + const uint32_t* words; // Words in the binary SPIR-V module. +@@ -267,6 +263,9 @@ spv_result_t Parser::parseModule() { + << _.words[0] << "'."; + } + _.requires_endian_conversion = !spvIsHostEndian(_.endian); ++ _.native_words = std::make_unique<uint32_t[]>(_.num_words); ++ for (size_t i = 0; i < _.num_words; i++) ++ _.native_words[i] = _.requires_endian_conversion ? spvFixWord(_.words[i], _.endian) : _.words[i]; + + // Process the header. + spv_header_t header; + +From 74df3cf1b49c9ae296ebbb16cf8e2e7b45584454 Mon Sep 17 00:00:00 2001 +From: Hugo Devillers <hugo@xol.io> +Date: Sat, 1 Jul 2023 12:42:04 +0200 +Subject: [PATCH 5/6] use native_words as a cache for spvFixWord + +--- + source/binary.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/source/binary.cpp b/source/binary.cpp +index 69bd082598..01322be0af 100644 +--- a/source/binary.cpp ++++ b/source/binary.cpp +@@ -173,7 +173,7 @@ class Parser { + // Returns the endian-corrected word at the given position. + uint32_t peekAt(size_t index) const { + assert(index < _.num_words); +- return spvFixWord(_.words[index], _.endian); ++ return _.native_words[index]; + } + + // Data members + +From 458eb86f866b489e93d17eee12f76207b93dd60d Mon Sep 17 00:00:00 2001 +From: Hugo Devillers <hugo@xol.io> +Date: Sat, 1 Jul 2023 16:59:06 +0200 +Subject: [PATCH 6/6] simplify and fix mismatched endian string parsing for + extract_source.cpp + +--- + tools/objdump/extract_source.cpp | 58 ++++---------------------------- + 1 file changed, 7 insertions(+), 51 deletions(-) + +diff --git a/tools/objdump/extract_source.cpp b/tools/objdump/extract_source.cpp +index 02959525c6..a179c722a0 100644 +--- a/tools/objdump/extract_source.cpp ++++ b/tools/objdump/extract_source.cpp +@@ -23,45 +23,12 @@ + #include "spirv-tools/libspirv.hpp" + #include "spirv/unified1/spirv.hpp" + #include "tools/util/cli_consumer.h" ++#include "source/binary.h" + + namespace { + + constexpr auto kDefaultEnvironment = SPV_ENV_UNIVERSAL_1_6; + +-// Extract a string literal from a given range. +-// Copies all the characters from `begin` to the first '\0' it encounters, while +-// removing escape patterns. +-// Not finding a '\0' before reaching `end` fails the extraction. +-// +-// Returns `true` if the extraction succeeded. +-// `output` value is undefined if false is returned. +-spv_result_t ExtractStringLiteral(const spv_position_t& loc, const char* begin, +- const char* end, std::string* output) { +- size_t sourceLength = std::distance(begin, end); +- std::string escapedString; +- escapedString.resize(sourceLength); +- +- size_t writeIndex = 0; +- size_t readIndex = 0; +- for (; readIndex < sourceLength; writeIndex++, readIndex++) { +- const char read = begin[readIndex]; +- if (read == '\0') { +- escapedString.resize(writeIndex); +- output->append(escapedString); +- return SPV_SUCCESS; +- } +- +- if (read == '\\') { +- ++readIndex; +- } +- escapedString[writeIndex] = begin[readIndex]; +- } +- +- spvtools::Error(spvtools::utils::CLIMessageConsumer, "", loc, +- "Missing NULL terminator for literal string."); +- return SPV_ERROR_INVALID_BINARY; +-} +- + spv_result_t extractOpString(const spv_position_t& loc, + const spv_parsed_instruction_t& instruction, + std::string* output) { +@@ -73,12 +40,8 @@ spv_result_t extractOpString(const spv_position_t& loc, + return SPV_ERROR_INVALID_BINARY; + } + +- const auto& operand = instruction.operands[1]; +- const char* stringBegin = +- reinterpret_cast<const char*>(instruction.words + operand.offset); +- const char* stringEnd = reinterpret_cast<const char*>( +- instruction.words + operand.offset + operand.num_words); +- return ExtractStringLiteral(loc, stringBegin, stringEnd, output); ++ *output = spvDecodeLiteralStringOperand(instruction, 1); ++ return SPV_SUCCESS; + } + + spv_result_t extractOpSourceContinued( +@@ -92,12 +55,8 @@ spv_result_t extractOpSourceContinued( + return SPV_ERROR_INVALID_BINARY; + } + +- const auto& operand = instruction.operands[0]; +- const char* stringBegin = +- reinterpret_cast<const char*>(instruction.words + operand.offset); +- const char* stringEnd = reinterpret_cast<const char*>( +- instruction.words + operand.offset + operand.num_words); +- return ExtractStringLiteral(loc, stringBegin, stringEnd, output); ++ *output = *output + spvDecodeLiteralStringOperand(instruction, 0); ++ return SPV_SUCCESS; + } + + spv_result_t extractOpSource(const spv_position_t& loc, +@@ -123,11 +82,8 @@ spv_result_t extractOpSource(const spv_position_t& loc, + return SPV_SUCCESS; + } + +- const char* stringBegin = +- reinterpret_cast<const char*>(instruction.words + 4); +- const char* stringEnd = +- reinterpret_cast<const char*>(instruction.words + instruction.num_words); +- return ExtractStringLiteral(loc, stringBegin, stringEnd, code); ++ *code = spvDecodeLiteralStringOperand(instruction, 3); ++ return SPV_SUCCESS; + } + + } // namespace |