mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-23 13:20:14 +01:00
spirv: Support big-endian strings
This should be all that's required for the SPIR-V parser to work in big-endian systems. SPIR-V requires that everything be in host byte-order except for strings which are always little-endian. Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Rhys Perry <pendingchaos02@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6090>
This commit is contained in:
parent
a8d8fbb9ce
commit
fb6b243c11
2 changed files with 35 additions and 10 deletions
|
|
@ -36,6 +36,9 @@
|
||||||
#include "util/u_math.h"
|
#include "util/u_math.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#if UTIL_ARCH_BIG_ENDIAN
|
||||||
|
#include <byteswap.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
vtn_log(struct vtn_builder *b, enum nir_spirv_debug_level level,
|
vtn_log(struct vtn_builder *b, enum nir_spirv_debug_level level,
|
||||||
|
|
@ -370,17 +373,39 @@ vtn_get_sampled_image(struct vtn_builder *b, uint32_t value_id)
|
||||||
return si;
|
return si;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static const char *
|
||||||
vtn_string_literal(struct vtn_builder *b, const uint32_t *words,
|
vtn_string_literal(struct vtn_builder *b, const uint32_t *words,
|
||||||
unsigned word_count, unsigned *words_used)
|
unsigned word_count, unsigned *words_used)
|
||||||
{
|
{
|
||||||
char *dup = ralloc_strndup(b, (char *)words, word_count * sizeof(*words));
|
/* From the SPIR-V spec:
|
||||||
if (words_used) {
|
*
|
||||||
/* Ammount of space taken by the string (including the null) */
|
* "A string is interpreted as a nul-terminated stream of characters.
|
||||||
unsigned len = strlen(dup) + 1;
|
* The character set is Unicode in the UTF-8 encoding scheme. The UTF-8
|
||||||
*words_used = DIV_ROUND_UP(len, sizeof(*words));
|
* 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."
|
||||||
|
*
|
||||||
|
* On big-endian, we need to byte-swap.
|
||||||
|
*/
|
||||||
|
#if UTIL_ARCH_BIG_ENDIAN
|
||||||
|
{
|
||||||
|
uint32_t *copy = ralloc_array(b, uint32_t, word_count);
|
||||||
|
for (unsigned i = 0; i < word_count; i++)
|
||||||
|
copy[i] = bswap_32(words[i]);
|
||||||
|
words = copy;
|
||||||
}
|
}
|
||||||
return dup;
|
#endif
|
||||||
|
|
||||||
|
const char *str = (char *)words;
|
||||||
|
const char *end = memchr(str, 0, word_count * 4);
|
||||||
|
vtn_fail_if(end == NULL, "String is not null-terminated");
|
||||||
|
|
||||||
|
if (words_used)
|
||||||
|
*words_used = DIV_ROUND_UP(end - str + 1, sizeof(*words));
|
||||||
|
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t *
|
const uint32_t *
|
||||||
|
|
@ -445,10 +470,10 @@ static void
|
||||||
vtn_handle_extension(struct vtn_builder *b, SpvOp opcode,
|
vtn_handle_extension(struct vtn_builder *b, SpvOp opcode,
|
||||||
const uint32_t *w, unsigned count)
|
const uint32_t *w, unsigned count)
|
||||||
{
|
{
|
||||||
const char *ext = (const char *)&w[2];
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case SpvOpExtInstImport: {
|
case SpvOpExtInstImport: {
|
||||||
struct vtn_value *val = vtn_push_value(b, w[1], vtn_value_type_extension);
|
struct vtn_value *val = vtn_push_value(b, w[1], vtn_value_type_extension);
|
||||||
|
const char *ext = vtn_string_literal(b, &w[2], count - 2, NULL);
|
||||||
if (strcmp(ext, "GLSL.std.450") == 0) {
|
if (strcmp(ext, "GLSL.std.450") == 0) {
|
||||||
val->ext_handler = vtn_handle_glsl450_instruction;
|
val->ext_handler = vtn_handle_glsl450_instruction;
|
||||||
} else if ((strcmp(ext, "SPV_AMD_gcn_shader") == 0)
|
} else if ((strcmp(ext, "SPV_AMD_gcn_shader") == 0)
|
||||||
|
|
|
||||||
|
|
@ -589,7 +589,7 @@ struct vtn_value {
|
||||||
struct vtn_decoration *decoration;
|
struct vtn_decoration *decoration;
|
||||||
struct vtn_type *type;
|
struct vtn_type *type;
|
||||||
union {
|
union {
|
||||||
char *str;
|
const char *str;
|
||||||
nir_constant *constant;
|
nir_constant *constant;
|
||||||
struct vtn_pointer *pointer;
|
struct vtn_pointer *pointer;
|
||||||
struct vtn_image_pointer *image;
|
struct vtn_image_pointer *image;
|
||||||
|
|
@ -639,7 +639,7 @@ struct vtn_builder {
|
||||||
* automatically by vtn_foreach_instruction.
|
* automatically by vtn_foreach_instruction.
|
||||||
*/
|
*/
|
||||||
size_t spirv_offset;
|
size_t spirv_offset;
|
||||||
char *file;
|
const char *file;
|
||||||
int line, col;
|
int line, col;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue