mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-01-28 13:05:02 -08:00
vkd3d-shader/spirv: Parse the SPIR-V magic number.
This commit is contained in:
parent
49fba97b0a
commit
6cac18e395
Notes:
Henri Verbeet
2024-12-09 16:17:46 +01:00
Approved-by: Giovanni Mascellani (@giomasce) Approved-by: Henri Verbeet (@hverbeet) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1239
@ -38,6 +38,8 @@
|
|||||||
# define VKD3D_SHADER_UNSUPPORTED_SPIRV_PARSER 0
|
# define VKD3D_SHADER_UNSUPPORTED_SPIRV_PARSER 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define VKD3D_SPIRV_HEADER_SIZE 5
|
||||||
|
|
||||||
#ifdef HAVE_SPIRV_TOOLS
|
#ifdef HAVE_SPIRV_TOOLS
|
||||||
# include "spirv-tools/libspirv.h"
|
# include "spirv-tools/libspirv.h"
|
||||||
|
|
||||||
@ -185,10 +187,25 @@ static bool vkd3d_spirv_validate(struct vkd3d_string_buffer *buffer, const struc
|
|||||||
|
|
||||||
#endif /* HAVE_SPIRV_TOOLS */
|
#endif /* HAVE_SPIRV_TOOLS */
|
||||||
|
|
||||||
|
struct spirv_colours
|
||||||
|
{
|
||||||
|
const char *reset;
|
||||||
|
const char *comment;
|
||||||
|
};
|
||||||
|
|
||||||
struct spirv_parser
|
struct spirv_parser
|
||||||
{
|
{
|
||||||
struct vkd3d_shader_location location;
|
struct vkd3d_shader_location location;
|
||||||
struct vkd3d_shader_message_context *message_context;
|
struct vkd3d_shader_message_context *message_context;
|
||||||
|
enum vkd3d_shader_compile_option_formatting_flags formatting;
|
||||||
|
struct spirv_colours colours;
|
||||||
|
bool failed;
|
||||||
|
|
||||||
|
const uint32_t *code;
|
||||||
|
size_t pos;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
struct vkd3d_string_buffer *text;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void VKD3D_PRINTF_FUNC(3, 4) spirv_parser_error(struct spirv_parser *parser,
|
static void VKD3D_PRINTF_FUNC(3, 4) spirv_parser_error(struct spirv_parser *parser,
|
||||||
@ -199,6 +216,90 @@ static void VKD3D_PRINTF_FUNC(3, 4) spirv_parser_error(struct spirv_parser *pars
|
|||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
vkd3d_shader_verror(parser->message_context, &parser->location, error, format, args);
|
vkd3d_shader_verror(parser->message_context, &parser->location, error, format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
parser->failed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t spirv_parser_read_u32(struct spirv_parser *parser)
|
||||||
|
{
|
||||||
|
if (parser->pos >= parser->size)
|
||||||
|
{
|
||||||
|
parser->failed = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parser->code[parser->pos++];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void VKD3D_PRINTF_FUNC(2, 3) spirv_parser_print_comment(struct spirv_parser *parser, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
if (!parser->text)
|
||||||
|
return;
|
||||||
|
|
||||||
|
va_start(args, format);
|
||||||
|
vkd3d_string_buffer_printf(parser->text, "%s; ", parser->colours.comment);
|
||||||
|
vkd3d_string_buffer_vprintf(parser->text, format, args);
|
||||||
|
vkd3d_string_buffer_printf(parser->text, "%s\n", parser->colours.reset);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum vkd3d_result spirv_parser_read_header(struct spirv_parser *parser)
|
||||||
|
{
|
||||||
|
uint32_t magic;
|
||||||
|
|
||||||
|
if (parser->pos > parser->size || parser->size - parser->pos < VKD3D_SPIRV_HEADER_SIZE)
|
||||||
|
{
|
||||||
|
spirv_parser_error(parser, VKD3D_SHADER_ERROR_SPV_INVALID_SHADER,
|
||||||
|
"Unexpected end while reading the SPIR-V header.");
|
||||||
|
return VKD3D_ERROR_INVALID_SHADER;
|
||||||
|
}
|
||||||
|
|
||||||
|
magic = spirv_parser_read_u32(parser);
|
||||||
|
|
||||||
|
if (magic != SpvMagicNumber)
|
||||||
|
{
|
||||||
|
spirv_parser_error(parser, VKD3D_SHADER_ERROR_SPV_INVALID_SHADER,
|
||||||
|
"Invalid magic number %#08x.", magic);
|
||||||
|
return VKD3D_ERROR_INVALID_SHADER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parser->formatting & VKD3D_SHADER_COMPILE_OPTION_FORMATTING_HEADER)
|
||||||
|
spirv_parser_print_comment(parser, "SPIR-V");
|
||||||
|
|
||||||
|
return VKD3D_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum vkd3d_result spirv_parser_parse(struct spirv_parser *parser, struct vkd3d_shader_code *text)
|
||||||
|
{
|
||||||
|
struct vkd3d_string_buffer buffer;
|
||||||
|
enum vkd3d_result ret;
|
||||||
|
|
||||||
|
if (text)
|
||||||
|
{
|
||||||
|
vkd3d_string_buffer_init(&buffer);
|
||||||
|
parser->text = &buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = spirv_parser_read_header(parser)) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (parser->failed)
|
||||||
|
{
|
||||||
|
ret = VKD3D_ERROR_INVALID_SHADER;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = VKD3D_ERROR_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (text)
|
||||||
|
{
|
||||||
|
if (TRACE_ON())
|
||||||
|
vkd3d_string_buffer_trace(&buffer);
|
||||||
|
vkd3d_string_buffer_cleanup(&buffer);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spirv_parser_cleanup(struct spirv_parser *parser)
|
static void spirv_parser_cleanup(struct spirv_parser *parser)
|
||||||
@ -207,8 +308,20 @@ static void spirv_parser_cleanup(struct spirv_parser *parser)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static enum vkd3d_result spirv_parser_init(struct spirv_parser *parser, const struct vkd3d_shader_code *source,
|
static enum vkd3d_result spirv_parser_init(struct spirv_parser *parser, const struct vkd3d_shader_code *source,
|
||||||
const char *source_name, struct vkd3d_shader_message_context *message_context)
|
const char *source_name, enum vkd3d_shader_compile_option_formatting_flags formatting,
|
||||||
|
struct vkd3d_shader_message_context *message_context)
|
||||||
{
|
{
|
||||||
|
static const struct spirv_colours no_colours =
|
||||||
|
{
|
||||||
|
.reset = "",
|
||||||
|
.comment = "",
|
||||||
|
};
|
||||||
|
static const struct spirv_colours colours =
|
||||||
|
{
|
||||||
|
.reset = "\x1b[m",
|
||||||
|
.comment = "\x1b[36m",
|
||||||
|
};
|
||||||
|
|
||||||
memset(parser, 0, sizeof(*parser));
|
memset(parser, 0, sizeof(*parser));
|
||||||
parser->location.source_name = source_name;
|
parser->location.source_name = source_name;
|
||||||
parser->message_context = message_context;
|
parser->message_context = message_context;
|
||||||
@ -220,6 +333,14 @@ static enum vkd3d_result spirv_parser_init(struct spirv_parser *parser, const st
|
|||||||
return VKD3D_ERROR_INVALID_SHADER;
|
return VKD3D_ERROR_INVALID_SHADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parser->formatting = formatting;
|
||||||
|
if (formatting & VKD3D_SHADER_COMPILE_OPTION_FORMATTING_COLOUR)
|
||||||
|
parser->colours = colours;
|
||||||
|
else
|
||||||
|
parser->colours = no_colours;
|
||||||
|
parser->code = source->code;
|
||||||
|
parser->size = source->size / 4;
|
||||||
|
|
||||||
return VKD3D_OK;
|
return VKD3D_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,11 +357,14 @@ static enum vkd3d_result vkd3d_spirv_binary_to_text(const struct vkd3d_shader_co
|
|||||||
|
|
||||||
MESSAGE("Creating a SPIR-V parser. This is unsupported; you get to keep all the pieces if it breaks.\n");
|
MESSAGE("Creating a SPIR-V parser. This is unsupported; you get to keep all the pieces if it breaks.\n");
|
||||||
|
|
||||||
if ((ret = spirv_parser_init(&parser, spirv, source_name, message_context)) < 0)
|
if ((ret = spirv_parser_init(&parser, spirv, source_name, formatting, message_context)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
ret = spirv_parser_parse(&parser, out);
|
||||||
|
|
||||||
spirv_parser_cleanup(&parser);
|
spirv_parser_cleanup(&parser);
|
||||||
|
|
||||||
return VKD3D_ERROR_NOT_IMPLEMENTED;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv, enum vkd3d_shader_spirv_environment environment)
|
static void vkd3d_spirv_dump(const struct vkd3d_shader_code *spirv, enum vkd3d_shader_spirv_environment environment)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user