mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-04-13 05:43:18 -07:00
vkd3d-shader/spirv: Handle "ValueEnum" operands.
This commit is contained in:
Notes:
Henri Verbeet
2025-03-10 15:22:45 +01:00
Approved-by: Giovanni Mascellani (@giomasce) Approved-by: Henri Verbeet (@hverbeet) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1382
@@ -27,11 +27,23 @@ sub opcode_id($)
|
||||
sprintf "0x%04x", shift;
|
||||
}
|
||||
|
||||
sub enumerant_id($)
|
||||
{
|
||||
my ($value) = @_;
|
||||
|
||||
sprintf "%#x", $value =~ /^0[xX]/ ? hex $value : $value;
|
||||
}
|
||||
|
||||
sub fix_name($)
|
||||
{
|
||||
shift =~ s/([A-Z]+)/_$1/rg;
|
||||
}
|
||||
|
||||
sub operand_category_name(_)
|
||||
{
|
||||
"SPIRV_PARSER_OPERAND_CATEGORY${\uc fix_name shift}";
|
||||
}
|
||||
|
||||
sub operand_type_name(_)
|
||||
{
|
||||
"SPIRV_PARSER_OPERAND_TYPE${\uc fix_name shift}";
|
||||
@@ -44,6 +56,46 @@ sub grammar_version($)
|
||||
"$grammar->{major_version}.$grammar->{minor_version}.$grammar->{revision}";
|
||||
}
|
||||
|
||||
sub print_enumerant(_)
|
||||
{
|
||||
my ($enumerant) = @_;
|
||||
my $indent = " " x 12;
|
||||
my $parameter_count = @{$enumerant->{parameters} // []};
|
||||
|
||||
if (!$parameter_count)
|
||||
{
|
||||
print $indent . "{${\enumerant_id $enumerant->{value}}, \"$enumerant->{enumerant}\"},\n";
|
||||
return;
|
||||
}
|
||||
|
||||
print $indent . "{\n";
|
||||
print $indent . " ${\enumerant_id $enumerant->{value}}, \"$enumerant->{enumerant}\", $parameter_count,\n";
|
||||
print $indent . " (enum spirv_parser_operand_type[])\n";
|
||||
print $indent . " {\n";
|
||||
print $indent . " ${\operand_type_name $_->{kind}},\n" foreach @{$enumerant->{parameters}};
|
||||
print $indent . " }\n";
|
||||
print $indent . "},\n";
|
||||
}
|
||||
|
||||
sub print_operand_type_info(_)
|
||||
{
|
||||
my ($type) = @_;
|
||||
my $enumerant_count = @{$type->{enumerants} // []};
|
||||
|
||||
print " [${\operand_type_name $type->{kind}}] =\n";
|
||||
print " {\n";
|
||||
print " \"$type->{kind}\", ${\operand_category_name $type->{category}}"
|
||||
. ($enumerant_count ? ", $enumerant_count,\n" : "\n");
|
||||
if ($enumerant_count)
|
||||
{
|
||||
print " (struct spirv_parser_enumerant[])\n";
|
||||
print " {\n";
|
||||
print_enumerant foreach @{$type->{enumerants}};
|
||||
print " }\n";
|
||||
}
|
||||
print " },\n";
|
||||
}
|
||||
|
||||
sub instruction_operand(_)
|
||||
{
|
||||
my ($operand) = @_;
|
||||
@@ -84,6 +136,11 @@ sub print_header($)
|
||||
print map {" * $_" =~ s/ +$//r . "\n"} @{$grammar->{copyright}};
|
||||
print " */\n\n";
|
||||
|
||||
print "enum spirv_parser_operand_category\n";
|
||||
print "{\n";
|
||||
print " ${\operand_category_name},\n" foreach sort keys %{{map {$_->{category}, undef} @operand_types}};
|
||||
print "};\n\n";
|
||||
|
||||
print "enum spirv_parser_operand_type\n";
|
||||
print "{\n";
|
||||
print " ${\operand_type_name $_->{kind}},\n" foreach @operand_types;
|
||||
@@ -92,10 +149,19 @@ sub print_header($)
|
||||
print "static const struct spirv_parser_operand_type_info\n";
|
||||
print "{\n";
|
||||
print " const char *name;\n";
|
||||
print " enum spirv_parser_operand_category category;\n";
|
||||
print " size_t enumerant_count;\n";
|
||||
print " const struct spirv_parser_enumerant\n";
|
||||
print " {\n";
|
||||
print " uint32_t value;\n";
|
||||
print " const char *name;\n";
|
||||
print " size_t parameter_count;\n";
|
||||
print " enum spirv_parser_operand_type *parameters;\n";
|
||||
print " } *enumerants;\n";
|
||||
print "}\n";
|
||||
print "spirv_parser_operand_type_info[] =\n";
|
||||
print "{\n";
|
||||
print " [${\operand_type_name $_->{kind}}] = {\"$_->{kind}\"},\n" foreach @operand_types;
|
||||
print_operand_type_info foreach @operand_types;
|
||||
print "};\n\n";
|
||||
|
||||
print "static const struct spirv_parser_opcode_info\n";
|
||||
|
@@ -215,6 +215,7 @@ struct spirv_colours
|
||||
const char *reset;
|
||||
const char *comment;
|
||||
const char *literal;
|
||||
const char *enumerant;
|
||||
const char *opcode;
|
||||
const char *id;
|
||||
};
|
||||
@@ -327,6 +328,13 @@ static void spirv_parser_print_uint_literal(struct spirv_parser *parser,
|
||||
prefix, parser->colours.literal, i, parser->colours.reset, suffix);
|
||||
}
|
||||
|
||||
static void spirv_parser_print_enumerant(struct spirv_parser *parser,
|
||||
struct vkd3d_string_buffer *buffer, const char *prefix, const char *name, const char *suffix)
|
||||
{
|
||||
vkd3d_string_buffer_printf(buffer, "%s%s%s%s%s",
|
||||
prefix, parser->colours.enumerant, name, parser->colours.reset, suffix);
|
||||
}
|
||||
|
||||
static void spirv_parser_print_opcode(struct spirv_parser *parser,
|
||||
struct vkd3d_string_buffer *buffer, const char *name)
|
||||
{
|
||||
@@ -385,6 +393,21 @@ static void spirv_parser_print_string_literal(struct spirv_parser *parser, struc
|
||||
vkd3d_string_buffer_printf(buffer, "%.*s%s\"%s", (int)(len - start), &s[start], parser->colours.reset, suffix);
|
||||
}
|
||||
|
||||
static const struct spirv_parser_enumerant *spirv_parser_get_enumerant(
|
||||
const struct spirv_parser_operand_type_info *info, uint32_t value)
|
||||
{
|
||||
const struct spirv_parser_enumerant *e;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < info->enumerant_count; ++i)
|
||||
{
|
||||
if ((e = &info->enumerants[i])->value == value)
|
||||
return e;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct spirv_parser_operand_type_info *spirv_parser_get_operand_type_info(enum spirv_parser_operand_type t)
|
||||
{
|
||||
if (t >= ARRAY_SIZE(spirv_parser_operand_type_info))
|
||||
@@ -498,6 +521,8 @@ static bool spirv_parser_parse_operand(struct spirv_parser *parser, struct vkd3d
|
||||
const char *opcode_name, enum spirv_parser_operand_type type, size_t end, uint32_t *result_id)
|
||||
{
|
||||
const struct spirv_parser_operand_type_info *info;
|
||||
const struct spirv_parser_enumerant *e;
|
||||
uint32_t word, i;
|
||||
|
||||
if (parser->pos >= end)
|
||||
{
|
||||
@@ -512,6 +537,26 @@ static bool spirv_parser_parse_operand(struct spirv_parser *parser, struct vkd3d
|
||||
return false;
|
||||
}
|
||||
|
||||
if (info->category == SPIRV_PARSER_OPERAND_CATEGORY_VALUE_ENUM)
|
||||
{
|
||||
word = spirv_parser_read_u32(parser);
|
||||
if (!(e = spirv_parser_get_enumerant(info, word)))
|
||||
{
|
||||
spirv_parser_warning(parser, VKD3D_SHADER_ERROR_SPV_NOT_IMPLEMENTED,
|
||||
"Unhandled \"%s\" enumeration value %#x.", info->name, word);
|
||||
return false;
|
||||
}
|
||||
spirv_parser_print_enumerant(parser, buffer, " ", e->name, "");
|
||||
|
||||
for (i = 0; i < e->parameter_count; ++i)
|
||||
{
|
||||
if (!spirv_parser_parse_operand(parser, buffer, opcode_name, e->parameters[i], end, result_id))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case SPIRV_PARSER_OPERAND_TYPE_ID_REF:
|
||||
@@ -702,6 +747,7 @@ static enum vkd3d_result spirv_parser_init(struct spirv_parser *parser, const st
|
||||
.reset = "",
|
||||
.comment = "",
|
||||
.literal = "",
|
||||
.enumerant = "",
|
||||
.opcode = "",
|
||||
.id = "",
|
||||
};
|
||||
@@ -710,6 +756,7 @@ static enum vkd3d_result spirv_parser_init(struct spirv_parser *parser, const st
|
||||
.reset = "\x1b[m",
|
||||
.comment = "\x1b[36m",
|
||||
.literal = "\x1b[95m",
|
||||
.enumerant = "\x1b[93m",
|
||||
.opcode = "\x1b[96;1m",
|
||||
.id = "\x1b[96m",
|
||||
};
|
||||
|
Reference in New Issue
Block a user