mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-09-12 18:50:22 -07:00
vkd3d-shader/fx: Read instruction arguments in full before printing them.
The binary format stores destination argument after sources. Each argument takes either 3 tokens or 5 tokens, when indexed. For simplicity read them all first, and print destination first. Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
This commit is contained in:
committed by
Henri Verbeet
parent
d6a4084321
commit
f525399545
Notes:
Henri Verbeet
2025-06-11 20:37:36 +02:00
Approved-by: Henri Verbeet (@hverbeet) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1559
@@ -4806,8 +4806,23 @@ struct fx_4_ctab_entry
|
|||||||
uint32_t default_value;
|
uint32_t default_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct fxlc_arg
|
||||||
|
{
|
||||||
|
uint32_t reg_type;
|
||||||
|
uint32_t address;
|
||||||
|
bool indexed;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32_t reg_type;
|
||||||
|
uint32_t address;
|
||||||
|
} index;
|
||||||
|
};
|
||||||
|
|
||||||
struct fxlvm_code
|
struct fxlvm_code
|
||||||
{
|
{
|
||||||
|
const uint32_t *ptr, *end;
|
||||||
|
bool failed;
|
||||||
|
|
||||||
const float *cli4;
|
const float *cli4;
|
||||||
uint32_t cli4_count;
|
uint32_t cli4_count;
|
||||||
|
|
||||||
@@ -4820,6 +4835,17 @@ struct fxlvm_code
|
|||||||
bool scalar;
|
bool scalar;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static uint32_t fxlvm_read_u32(struct fxlvm_code *code)
|
||||||
|
{
|
||||||
|
if (code->end == code->ptr)
|
||||||
|
{
|
||||||
|
code->failed = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *code->ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
static void fx_4_parse_print_swizzle(struct fx_parser *parser, const struct fxlvm_code *code, unsigned int addr)
|
static void fx_4_parse_print_swizzle(struct fx_parser *parser, const struct fxlvm_code *code, unsigned int addr)
|
||||||
{
|
{
|
||||||
unsigned int comp_count = code->scalar ? 1 : code->comp_count;
|
unsigned int comp_count = code->scalar ? 1 : code->comp_count;
|
||||||
@@ -4830,7 +4856,7 @@ static void fx_4_parse_print_swizzle(struct fx_parser *parser, const struct fxlv
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void fx_4_parse_fxlc_constant_argument(struct fx_parser *parser,
|
static void fx_4_parse_fxlc_constant_argument(struct fx_parser *parser,
|
||||||
const struct fx_4_fxlc_argument *arg, const struct fxlvm_code *code)
|
const struct fxlc_arg *arg, const struct fxlvm_code *code)
|
||||||
{
|
{
|
||||||
uint32_t i, offset, register_index = arg->address / 4; /* Address counts in components. */
|
uint32_t i, offset, register_index = arg->address / 4; /* Address counts in components. */
|
||||||
|
|
||||||
@@ -4855,18 +4881,32 @@ static void fx_4_parse_fxlc_constant_argument(struct fx_parser *parser,
|
|||||||
vkd3d_string_buffer_printf(&parser->buffer, "(var-not-found)");
|
vkd3d_string_buffer_printf(&parser->buffer, "(var-not-found)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fx_4_parse_fxlc_argument(struct fx_parser *parser, uint32_t offset, const struct fxlvm_code *code)
|
static void fx_parse_fxlc_argument(struct fx_parser *parser, struct fxlc_arg *arg, struct fxlvm_code *code)
|
||||||
|
{
|
||||||
|
uint32_t flags;
|
||||||
|
|
||||||
|
memset(arg, 0, sizeof(*arg));
|
||||||
|
|
||||||
|
flags = fxlvm_read_u32(code);
|
||||||
|
if (flags)
|
||||||
|
{
|
||||||
|
arg->indexed = true;
|
||||||
|
arg->index.reg_type = fxlvm_read_u32(code);
|
||||||
|
arg->index.address = fxlvm_read_u32(code);
|
||||||
|
}
|
||||||
|
arg->reg_type = fxlvm_read_u32(code);
|
||||||
|
arg->address = fxlvm_read_u32(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fx_print_fxlc_argument(struct fx_parser *parser, const struct fxlc_arg *arg, struct fxlvm_code *code)
|
||||||
{
|
{
|
||||||
struct fx_4_fxlc_argument arg;
|
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
|
|
||||||
fx_parser_read_unstructured(parser, &arg, offset, sizeof(arg));
|
switch (arg->reg_type)
|
||||||
|
|
||||||
switch (arg.reg_type)
|
|
||||||
{
|
{
|
||||||
case FX_FXLC_REG_LITERAL:
|
case FX_FXLC_REG_LITERAL:
|
||||||
count = code->scalar ? 1 : code->comp_count;
|
count = code->scalar ? 1 : code->comp_count;
|
||||||
if (arg.address >= code->cli4_count || count > code->cli4_count - arg.address)
|
if (arg->address >= code->cli4_count || count > code->cli4_count - arg->address)
|
||||||
{
|
{
|
||||||
vkd3d_string_buffer_printf(&parser->buffer, "(<out-of-bounds>)");
|
vkd3d_string_buffer_printf(&parser->buffer, "(<out-of-bounds>)");
|
||||||
parser->failed = true;
|
parser->failed = true;
|
||||||
@@ -4874,42 +4914,97 @@ static void fx_4_parse_fxlc_argument(struct fx_parser *parser, uint32_t offset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
vkd3d_string_buffer_printf(&parser->buffer, "(");
|
vkd3d_string_buffer_printf(&parser->buffer, "(");
|
||||||
vkd3d_string_buffer_print_f32(&parser->buffer, code->cli4[arg.address]);
|
vkd3d_string_buffer_print_f32(&parser->buffer, code->cli4[arg->address]);
|
||||||
for (unsigned int i = 1; i < code->comp_count; ++i)
|
for (unsigned int i = 1; i < code->comp_count; ++i)
|
||||||
{
|
{
|
||||||
vkd3d_string_buffer_printf(&parser->buffer, ", ");
|
vkd3d_string_buffer_printf(&parser->buffer, ", ");
|
||||||
vkd3d_string_buffer_print_f32(&parser->buffer, code->cli4[arg.address + (code->scalar ? 0 : i)]);
|
vkd3d_string_buffer_print_f32(&parser->buffer, code->cli4[arg->address + (code->scalar ? 0 : i)]);
|
||||||
}
|
}
|
||||||
vkd3d_string_buffer_printf(&parser->buffer, ")");
|
vkd3d_string_buffer_printf(&parser->buffer, ")");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FX_FXLC_REG_CB:
|
case FX_FXLC_REG_CB:
|
||||||
fx_4_parse_fxlc_constant_argument(parser, &arg, code);
|
fx_4_parse_fxlc_constant_argument(parser, arg, code);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FX_FXLC_REG_OUTPUT:
|
case FX_FXLC_REG_OUTPUT:
|
||||||
case FX_FXLC_REG_TEMP:
|
case FX_FXLC_REG_TEMP:
|
||||||
if (arg.reg_type == FX_FXLC_REG_OUTPUT)
|
if (arg->reg_type == FX_FXLC_REG_OUTPUT)
|
||||||
vkd3d_string_buffer_printf(&parser->buffer, "expr");
|
vkd3d_string_buffer_printf(&parser->buffer, "expr");
|
||||||
else
|
else
|
||||||
vkd3d_string_buffer_printf(&parser->buffer, "r%u", arg.address / 4);
|
vkd3d_string_buffer_printf(&parser->buffer, "r%u", arg->address / 4);
|
||||||
fx_4_parse_print_swizzle(parser, code, arg.address);
|
fx_4_parse_print_swizzle(parser, code, arg->address);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
vkd3d_string_buffer_printf(&parser->buffer, "<unknown register %u>", arg.reg_type);
|
vkd3d_string_buffer_printf(&parser->buffer, "<unknown register %u>", arg->reg_type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fx_parse_fxlvm_expression(struct fx_parser *parser, struct fxlvm_code *code)
|
||||||
|
{
|
||||||
|
struct fxlc_arg args[9];
|
||||||
|
uint32_t ins_count;
|
||||||
|
size_t i, j;
|
||||||
|
|
||||||
|
ins_count = fxlvm_read_u32(code);
|
||||||
|
|
||||||
|
parse_fx_start_indent(parser);
|
||||||
|
|
||||||
|
for (i = 0; i < ins_count; ++i)
|
||||||
|
{
|
||||||
|
uint32_t instr, opcode, src_count;
|
||||||
|
|
||||||
|
instr = fxlvm_read_u32(code);
|
||||||
|
src_count = fxlvm_read_u32(code);
|
||||||
|
|
||||||
|
if (src_count >= ARRAY_SIZE(args))
|
||||||
|
{
|
||||||
|
fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA,
|
||||||
|
"Unexpected instruction source count %u.", src_count);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sources entries are followed by the destination, first read them all.
|
||||||
|
Output format is "opcode dst, src[0]...src[n]". */
|
||||||
|
for (j = 0; j < src_count; ++j)
|
||||||
|
fx_parse_fxlc_argument(parser, &args[j], code);
|
||||||
|
fx_parse_fxlc_argument(parser, &args[src_count], code);
|
||||||
|
|
||||||
|
opcode = (instr >> FX_FXLC_OPCODE_SHIFT) & FX_FXLC_OPCODE_MASK;
|
||||||
|
code->comp_count = instr & FX_FXLC_COMP_COUNT_MASK;
|
||||||
|
|
||||||
|
parse_fx_print_indent(parser);
|
||||||
|
vkd3d_string_buffer_printf(&parser->buffer, "%s ", get_fxlc_opcode_name(opcode));
|
||||||
|
|
||||||
|
code->scalar = false;
|
||||||
|
fx_print_fxlc_argument(parser, &args[src_count], code);
|
||||||
|
vkd3d_string_buffer_printf(&parser->buffer, ", ");
|
||||||
|
|
||||||
|
for (j = 0; j < src_count; ++j)
|
||||||
|
{
|
||||||
|
/* Scalar modifier applies only to the first source. */
|
||||||
|
code->scalar = j == 0 && !!(instr & FX_FXLC_IS_SCALAR_MASK);
|
||||||
|
fx_print_fxlc_argument(parser, &args[j], code);
|
||||||
|
if (j < src_count - 1)
|
||||||
|
vkd3d_string_buffer_printf(&parser->buffer, ", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
vkd3d_string_buffer_printf(&parser->buffer, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_fx_end_indent(parser);
|
||||||
|
}
|
||||||
|
|
||||||
static void fx_4_parse_fxlvm_expression(struct fx_parser *parser, uint32_t offset)
|
static void fx_4_parse_fxlvm_expression(struct fx_parser *parser, uint32_t offset)
|
||||||
{
|
{
|
||||||
struct vkd3d_shader_dxbc_section_desc *section, fxlc, cli4, ctab;
|
struct vkd3d_shader_dxbc_section_desc *section, fxlc, cli4, ctab;
|
||||||
struct vkd3d_shader_dxbc_desc dxbc_desc;
|
struct vkd3d_shader_dxbc_desc dxbc_desc;
|
||||||
|
struct fxlvm_code code = { 0 };
|
||||||
struct vkd3d_shader_code dxbc;
|
struct vkd3d_shader_code dxbc;
|
||||||
uint32_t size, ins_count;
|
uint32_t size;
|
||||||
struct fxlvm_code code;
|
size_t i;
|
||||||
size_t i, j;
|
|
||||||
|
|
||||||
offset = fx_parser_read_unstructured(parser, &size, offset, sizeof(size));
|
offset = fx_parser_read_unstructured(parser, &size, offset, sizeof(size));
|
||||||
|
|
||||||
@@ -4962,47 +5057,10 @@ static void fx_4_parse_fxlvm_expression(struct fx_parser *parser, uint32_t offse
|
|||||||
ctab_offset + consts_offset, code.ctab_count * sizeof(*code.constants));
|
ctab_offset + consts_offset, code.ctab_count * sizeof(*code.constants));
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += (size_t)fxlc.data.code - (size_t)dxbc.code;
|
code.ptr = fxlc.data.code;
|
||||||
offset = fx_parser_read_unstructured(parser, &ins_count, offset, sizeof(ins_count));
|
code.end = (uint32_t *)((uint8_t *)fxlc.data.code + fxlc.data.size);
|
||||||
|
|
||||||
parse_fx_start_indent(parser);
|
fx_parse_fxlvm_expression(parser, &code);
|
||||||
|
|
||||||
for (i = 0; i < ins_count; ++i)
|
|
||||||
{
|
|
||||||
uint32_t instr, opcode, src_count;
|
|
||||||
struct fx_4_fxlc_argument arg;
|
|
||||||
|
|
||||||
offset = fx_parser_read_unstructured(parser, &instr, offset, sizeof(instr));
|
|
||||||
offset = fx_parser_read_unstructured(parser, &src_count, offset, sizeof(src_count));
|
|
||||||
|
|
||||||
opcode = (instr >> FX_FXLC_OPCODE_SHIFT) & FX_FXLC_OPCODE_MASK;
|
|
||||||
code.comp_count = instr & FX_FXLC_COMP_COUNT_MASK;
|
|
||||||
code.scalar = false;
|
|
||||||
|
|
||||||
parse_fx_print_indent(parser);
|
|
||||||
vkd3d_string_buffer_printf(&parser->buffer, "%s ", get_fxlc_opcode_name(opcode));
|
|
||||||
|
|
||||||
/* Destination first. */
|
|
||||||
fx_4_parse_fxlc_argument(parser, offset + sizeof(arg) * src_count, &code);
|
|
||||||
|
|
||||||
for (j = 0; j < src_count; ++j)
|
|
||||||
{
|
|
||||||
vkd3d_string_buffer_printf(&parser->buffer, ", ");
|
|
||||||
|
|
||||||
/* Scalar modifier applies only to first source. */
|
|
||||||
code.scalar = j == 0 && !!(instr & FX_FXLC_IS_SCALAR_MASK);
|
|
||||||
fx_4_parse_fxlc_argument(parser, offset, &code);
|
|
||||||
|
|
||||||
offset += sizeof(arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Destination */
|
|
||||||
offset += sizeof(arg);
|
|
||||||
|
|
||||||
vkd3d_string_buffer_printf(&parser->buffer, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
parse_fx_end_indent(parser);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fx_4_parse_state_object_initializer(struct fx_parser *parser, uint32_t count,
|
static void fx_4_parse_state_object_initializer(struct fx_parser *parser, uint32_t count,
|
||||||
|
Reference in New Issue
Block a user