From: Nikolay Sivov nsivov@codeweavers.com
--- include/vkd3d_shader.h | 2 + libs/vkd3d-shader/d3d_asm.c | 78 ++-- libs/vkd3d-shader/d3dbc.c | 459 +++++++++++++++++++++++ libs/vkd3d-shader/vkd3d_shader_main.c | 38 ++ libs/vkd3d-shader/vkd3d_shader_private.h | 15 + programs/vkd3d-compiler/main.c | 5 + 6 files changed, 568 insertions(+), 29 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index f112e7c75..fc8e793bb 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -672,6 +672,8 @@ enum vkd3d_shader_source_type */ VKD3D_SHADER_SOURCE_DXBC_DXIL,
+ VKD3D_SHADER_SOURCE_TX_BYTECODE, + VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_SOURCE_TYPE), };
diff --git a/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d-shader/d3d_asm.c index 566680be7..69c70f16a 100644 --- a/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d-shader/d3d_asm.c @@ -30,8 +30,12 @@ static const char * const shader_opcode_names[] = { [VKD3DSIH_ABS ] = "abs", + [VKD3DSIH_ACOS ] = "acos", [VKD3DSIH_ADD ] = "add", [VKD3DSIH_AND ] = "and", + [VKD3DSIH_ASIN ] = "asin", + [VKD3DSIH_ATAN ] = "atan", + [VKD3DSIH_ATAN2 ] = "atan2", [VKD3DSIH_ATOMIC_AND ] = "atomic_and", [VKD3DSIH_ATOMIC_CMP_STORE ] = "atomic_cmp_store", [VKD3DSIH_ATOMIC_IADD ] = "atomic_iadd", @@ -56,6 +60,7 @@ static const char * const shader_opcode_names[] = [VKD3DSIH_CND ] = "cnd", [VKD3DSIH_CONTINUE ] = "continue", [VKD3DSIH_CONTINUEP ] = "continuec", + [VKD3DSIH_COS ] = "cos", [VKD3DSIH_COUNTBITS ] = "countbits", [VKD3DSIH_CRS ] = "crs", [VKD3DSIH_CUT ] = "cut", @@ -118,6 +123,8 @@ static const char * const shader_opcode_names[] = [VKD3DSIH_DMOVC ] = "dmovc", [VKD3DSIH_DMUL ] = "dmul", [VKD3DSIH_DNE ] = "dne", + [VKD3DSIH_DOT ] = "dot", + [VKD3DSIH_DOT_SWIZ ] = "d3ds_dotswiz", [VKD3DSIH_DP2 ] = "dp2", [VKD3DSIH_DP2ADD ] = "dp2add", [VKD3DSIH_DP3 ] = "dp3", @@ -229,6 +236,9 @@ static const char * const shader_opcode_names[] = [VKD3DSIH_MSAD ] = "msad", [VKD3DSIH_MUL ] = "mul", [VKD3DSIH_NE ] = "ne", + [VKD3DSIH_NEG ] = "neg", + [VKD3DSIH_NOISE ] = "noise", + [VKD3DSIH_NOISE_SWIZ ] = "d3ds_noiseswiz", [VKD3DSIH_NOP ] = "nop", [VKD3DSIH_NOT ] = "not", [VKD3DSIH_NRM ] = "nrm", @@ -262,6 +272,7 @@ static const char * const shader_opcode_names[] = [VKD3DSIH_SETP ] = "setp", [VKD3DSIH_SGE ] = "sge", [VKD3DSIH_SGN ] = "sgn", + [VKD3DSIH_SIN ] = "sin", [VKD3DSIH_SINCOS ] = "sincos", [VKD3DSIH_SLT ] = "slt", [VKD3DSIH_SQRT ] = "sqrt", @@ -753,7 +764,7 @@ static void shader_dump_decl_usage(struct vkd3d_d3d_asm_compiler *compiler, }
static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, - const struct vkd3d_shader_src_param *param); + unsigned int component_count, const struct vkd3d_shader_src_param *param);
static void shader_print_float_literal(struct vkd3d_d3d_asm_compiler *compiler, const char *prefix, float f, const char *suffix) @@ -825,7 +836,7 @@ static void shader_print_subscript(struct vkd3d_d3d_asm_compiler *compiler, vkd3d_string_buffer_printf(&compiler->buffer, "["); if (rel_addr) { - shader_dump_src_param(compiler, rel_addr); + shader_dump_src_param(compiler, 4, rel_addr); vkd3d_string_buffer_printf(&compiler->buffer, " + "); } shader_print_uint_literal(compiler, "", offset, "]"); @@ -842,10 +853,10 @@ static void shader_print_subscript_range(struct vkd3d_d3d_asm_compiler *compiler }
static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const struct vkd3d_shader_register *reg, - bool is_declaration) + unsigned int component_count, bool is_declaration) { struct vkd3d_string_buffer *buffer = &compiler->buffer; - unsigned int offset = reg->idx[0].offset; + unsigned int i, offset = reg->idx[0].offset; bool is_descriptor = false;
static const char * const rastout_reg_names[] = {"oPos", "oFog", "oPts"}; @@ -1108,9 +1119,8 @@ static void shader_dump_register(struct vkd3d_d3d_asm_compiler *compiler, const { case VKD3D_DATA_FLOAT: shader_print_float_literal(compiler, "", reg->u.immconst_float[0], ""); - shader_print_float_literal(compiler, ", ", reg->u.immconst_float[1], ""); - shader_print_float_literal(compiler, ", ", reg->u.immconst_float[2], ""); - shader_print_float_literal(compiler, ", ", reg->u.immconst_float[3], ""); + for (i = 1; i < component_count; ++i) + shader_print_float_literal(compiler, ", ", reg->u.immconst_float[i], ""); break; case VKD3D_DATA_INT: shader_print_int_literal(compiler, "", reg->u.immconst_uint[0], ""); @@ -1262,7 +1272,7 @@ static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler, struct vkd3d_string_buffer *buffer = &compiler->buffer; uint32_t write_mask = param->write_mask;
- shader_dump_register(compiler, ¶m->reg, is_declaration); + shader_dump_register(compiler, ¶m->reg, 4, is_declaration);
if (write_mask && param->reg.dimension == VSIR_DIMENSION_VEC4) { @@ -1288,7 +1298,7 @@ static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler, }
static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, - const struct vkd3d_shader_src_param *param) + unsigned int component_count, const struct vkd3d_shader_src_param *param) { enum vkd3d_shader_src_modifier src_modifier = param->modifiers; struct vkd3d_string_buffer *buffer = &compiler->buffer; @@ -1308,7 +1318,7 @@ static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, if (src_modifier == VKD3DSPSM_ABS || src_modifier == VKD3DSPSM_ABSNEG) shader_addline(buffer, "|");
- shader_dump_register(compiler, ¶m->reg, false); + shader_dump_register(compiler, ¶m->reg, component_count, false);
switch (src_modifier) { @@ -1332,26 +1342,27 @@ static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, if (param->reg.type != VKD3DSPR_IMMCONST && param->reg.type != VKD3DSPR_IMMCONST64 && param->reg.dimension == VSIR_DIMENSION_VEC4) { - unsigned int swizzle_x = vkd3d_swizzle_get_component(swizzle, 0); - unsigned int swizzle_y = vkd3d_swizzle_get_component(swizzle, 1); - unsigned int swizzle_z = vkd3d_swizzle_get_component(swizzle, 2); - unsigned int swizzle_w = vkd3d_swizzle_get_component(swizzle, 3); + unsigned int i, components[4]; + char swizzle_str[5];
static const char swizzle_chars[] = "xyzw";
- if (swizzle_x == swizzle_y - && swizzle_x == swizzle_z - && swizzle_x == swizzle_w) + for (i = 0; i < 4; ++i) { - shader_addline(buffer, ".%s%c%s", compiler->colours.swizzle, - swizzle_chars[swizzle_x], compiler->colours.reset); + components[i] = vkd3d_swizzle_get_component(swizzle, i); + swizzle_str[i] = swizzle_chars[components[i]]; } - else + swizzle_str[4] = 0; + + if (components[0] == components[1] + && components[0] == components[2] + && components[0] == components[3]) { - shader_addline(buffer, ".%s%c%c%c%c%s", compiler->colours.swizzle, - swizzle_chars[swizzle_x], swizzle_chars[swizzle_y], - swizzle_chars[swizzle_z], swizzle_chars[swizzle_w], compiler->colours.reset); + component_count = 1; } + swizzle_str[component_count] = 0; + + shader_addline(buffer, ".%s%s%s", compiler->colours.swizzle, swizzle_str, compiler->colours.reset); } if (src_modifier == VKD3DSPSM_ABS || src_modifier == VKD3DSPSM_ABSNEG) shader_addline(buffer, "|"); @@ -1586,16 +1597,24 @@ static void shader_print_opcode(struct vkd3d_d3d_asm_compiler *compiler, enum vk shader_opcode_names[opcode], compiler->colours.reset); }
+static unsigned int shader_get_src_component_count(const struct vkd3d_d3d_asm_compiler *compiler, + const struct vkd3d_shader_instruction *ins) +{ + if (compiler->shader_version.type != VKD3D_SHADER_TYPE_TEXTURE) + return 4; + return vkd3d_popcount(ins->dst[0].write_mask); +} + static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, const struct vkd3d_shader_instruction *ins) { struct vkd3d_string_buffer *buffer = &compiler->buffer; - unsigned int i; + unsigned int i, component_count;
if (ins->predicate) { vkd3d_string_buffer_printf(buffer, "("); - shader_dump_src_param(compiler, ins->predicate); + shader_dump_src_param(compiler, 4, ins->predicate); vkd3d_string_buffer_printf(buffer, ") "); }
@@ -1613,13 +1632,13 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, shader_dump_decl_usage(compiler, &ins->declaration.semantic, ins->flags); shader_dump_ins_modifiers(compiler, &ins->declaration.semantic.resource.reg); vkd3d_string_buffer_printf(buffer, "%s ", compiler->colours.reset); - shader_dump_register(compiler, &ins->declaration.semantic.resource.reg.reg, true); + shader_dump_register(compiler, &ins->declaration.semantic.resource.reg.reg, 4, true); shader_dump_register_space(compiler, ins->declaration.semantic.resource.range.space); break;
case VKD3DSIH_DCL_CONSTANT_BUFFER: vkd3d_string_buffer_printf(buffer, " "); - shader_dump_register(compiler, &ins->declaration.cb.src.reg, true); + shader_dump_register(compiler, &ins->declaration.cb.src.reg, 4, true); if (shader_ver_ge(&compiler->shader_version, 5, 1)) shader_print_subscript(compiler, ins->declaration.cb.size, NULL); shader_addline(buffer, ", %s", @@ -1730,7 +1749,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler,
case VKD3DSIH_DCL_SAMPLER: vkd3d_string_buffer_printf(buffer, " "); - shader_dump_register(compiler, &ins->declaration.sampler.src.reg, true); + shader_dump_register(compiler, &ins->declaration.sampler.src.reg, 4, true); if (ins->flags == VKD3DSI_SAMPLER_COMPARISON_MODE) shader_addline(buffer, ", comparisonMode"); shader_dump_register_space(compiler, ins->declaration.sampler.range.space); @@ -1855,12 +1874,13 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, shader_addline(buffer, !i ? " " : ", "); shader_dump_dst_param(compiler, &ins->dst[i], false); } + component_count = shader_get_src_component_count(compiler, ins);
/* Other source tokens */ for (i = ins->dst_count; i < (ins->dst_count + ins->src_count); ++i) { shader_addline(buffer, !i ? " " : ", "); - shader_dump_src_param(compiler, &ins->src[i - ins->dst_count]); + shader_dump_src_param(compiler, component_count, &ins->src[i - ins->dst_count]); } break; } diff --git a/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d-shader/d3dbc.c index 67fa32710..1f00c6f01 100644 --- a/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d-shader/d3dbc.c @@ -29,6 +29,7 @@
#define VKD3D_SM1_VS 0xfffeu #define VKD3D_SM1_PS 0xffffu +#define VKD3D_SM1_TX 0x5458u
#define VKD3D_SM1_DCL_USAGE_SHIFT 0u #define VKD3D_SM1_DCL_USAGE_MASK (0xfu << VKD3D_SM1_DCL_USAGE_SHIFT) @@ -219,6 +220,94 @@ struct vkd3d_shader_sm1_parser uint32_t constant_def_mask[3][MAX_CONSTANT_COUNT / 32]; };
+enum vkd3d_fxlc_opcode +{ + VKD3D_FXLC_OP_NOP = 0x000, + VKD3D_FXLC_OP_MOV = 0x100, + VKD3D_FXLC_OP_NEG = 0x101, + VKD3D_FXLC_OP_RCP = 0x103, + VKD3D_FXLC_OP_FRC = 0x104, + VKD3D_FXLC_OP_EXP = 0x105, + VKD3D_FXLC_OP_LOG = 0x106, + VKD3D_FXLC_OP_RSQ = 0x107, + VKD3D_FXLC_OP_SIN = 0x108, + VKD3D_FXLC_OP_COS = 0x109, + VKD3D_FXLC_OP_ASIN = 0x10a, + VKD3D_FXLC_OP_ACOS = 0x10b, + VKD3D_FXLC_OP_ATAN = 0x10c, + VKD3D_FXLC_OP_MIN = 0x200, + VKD3D_FXLC_OP_MAX = 0x201, + VKD3D_FXLC_OP_LT = 0x202, + VKD3D_FXLC_OP_GE = 0x203, + VKD3D_FXLC_OP_ADD = 0x204, + VKD3D_FXLC_OP_MUL = 0x205, + VKD3D_FXLC_OP_ATAN2 = 0x206, + VKD3D_FXLC_OP_DIV = 0x208, + VKD3D_FXLC_OP_CMP = 0x300, + VKD3D_FXLC_OP_DOT = 0x500, + VKD3D_FXLC_OP_NOISE = 0x502, + VKD3D_FXLC_OP_DOT_SWIZ = 0x70e, + VKD3D_FXLC_OP_NOISE_SWIZ = 0x711, +}; + +struct vkd3d_fxlc_opcode_info +{ + enum vkd3d_fxlc_opcode fxlc_opcode; + enum vkd3d_shader_opcode vkd3d_opcode; +}; + +static const struct vkd3d_fxlc_opcode_info tx_opcode_table[] = +{ + {VKD3D_FXLC_OP_NOP, VKD3DSIH_NOP}, + {VKD3D_FXLC_OP_MOV, VKD3DSIH_MOV}, + {VKD3D_FXLC_OP_NEG, VKD3DSIH_NEG}, + {VKD3D_FXLC_OP_RCP, VKD3DSIH_RCP}, + {VKD3D_FXLC_OP_FRC, VKD3DSIH_FRC}, + {VKD3D_FXLC_OP_EXP, VKD3DSIH_EXP}, + {VKD3D_FXLC_OP_LOG, VKD3DSIH_LOG}, + {VKD3D_FXLC_OP_RSQ, VKD3DSIH_RSQ}, + {VKD3D_FXLC_OP_SIN, VKD3DSIH_SIN}, + {VKD3D_FXLC_OP_COS, VKD3DSIH_COS}, + {VKD3D_FXLC_OP_ASIN, VKD3DSIH_ASIN}, + {VKD3D_FXLC_OP_ACOS, VKD3DSIH_ACOS}, + {VKD3D_FXLC_OP_ATAN, VKD3DSIH_ATAN}, + {VKD3D_FXLC_OP_MIN, VKD3DSIH_MIN}, + {VKD3D_FXLC_OP_MAX, VKD3DSIH_MAX}, + {VKD3D_FXLC_OP_LT, VKD3DSIH_LT}, + {VKD3D_FXLC_OP_GE, VKD3DSIH_GE}, + {VKD3D_FXLC_OP_ADD, VKD3DSIH_ADD}, + {VKD3D_FXLC_OP_MUL, VKD3DSIH_MUL}, + {VKD3D_FXLC_OP_ATAN2, VKD3DSIH_ATAN2}, + {VKD3D_FXLC_OP_DIV, VKD3DSIH_DIV}, + {VKD3D_FXLC_OP_CMP, VKD3DSIH_CMP}, + {VKD3D_FXLC_OP_DOT, VKD3DSIH_DOT}, + {VKD3D_FXLC_OP_NOISE, VKD3DSIH_NOISE}, + {VKD3D_FXLC_OP_DOT_SWIZ, VKD3DSIH_DOT_SWIZ}, + {VKD3D_FXLC_OP_NOISE_SWIZ, VKD3DSIH_NOISE_SWIZ}, + {0, VKD3DSIH_INVALID}, +}; + +struct vkd3d_shader_tx_parser +{ + const struct vkd3d_fxlc_opcode_info *opcode_table; + const uint32_t *start, *end, *ptr; + struct + { + const uint32_t *start, *end; + } fxlc; + struct + { + const double *table; + unsigned int size; + } clit; + struct vkd3d_shader_parser p; +}; + +static struct vkd3d_shader_tx_parser *vkd3d_shader_tx_parser(struct vkd3d_shader_parser *parser) +{ + return CONTAINING_RECORD(parser, struct vkd3d_shader_tx_parser, p); +} + /* This table is not order or position dependent. */ static const struct vkd3d_sm1_opcode_info vs_opcode_table[] = { @@ -1284,6 +1373,135 @@ static enum vkd3d_result shader_sm1_init(struct vkd3d_shader_sm1_parser *sm1, return VKD3D_OK; }
+static void shader_tx_read_sections(struct vkd3d_shader_tx_parser *tx) +{ + const uint32_t **ptr = &tx->ptr, *section; + unsigned int size; + size_t remaining; + uint32_t token; + + if (*ptr >= tx->end) + return; + + remaining = tx->end - *ptr; + + token = **ptr; + + while ((token & VKD3D_SM1_OPCODE_MASK) == VKD3D_SM1_OP_COMMENT) + { + size = (token & VKD3D_SM1_COMMENT_SIZE_MASK) >> VKD3D_SM1_COMMENT_SIZE_SHIFT; + + if (size > --remaining) + { + vkd3d_shader_parser_error(&tx->p, VKD3D_SHADER_ERROR_D3DBC_UNEXPECTED_EOF, + "Encountered a %u token comment, but only %zu token(s) is/are remaining.", + size, remaining); + return; + } + + section = ++(*ptr); + remaining -= size; + *ptr += size; + + if (*section == TAG_FXLC) + { + tx->fxlc.start = section + 1; + tx->fxlc.end = section + size; + } + else if (*section == TAG_CLIT) + { + ++section; + + tx->clit.size = *section++; + tx->clit.table = (double *)section; + } + + if (!remaining) + break; + token = **ptr; + } +} + +static void shader_tx_destroy(struct vkd3d_shader_parser *parser) +{ + struct vkd3d_shader_tx_parser *tx = vkd3d_shader_tx_parser(parser); + + shader_instruction_array_destroy(&parser->instructions); + vkd3d_free(tx); +} + +const struct vkd3d_shader_parser_ops shader_tx_parser_ops = +{ + .parser_destroy = shader_tx_destroy, +}; + +static enum vkd3d_result shader_tx_init(struct vkd3d_shader_tx_parser *tx, + const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context) +{ + const struct vkd3d_shader_location location = {.source_name = compile_info->source_name}; + const uint32_t *code = compile_info->source.code; + size_t code_size = compile_info->source.size; + struct vkd3d_shader_desc *shader_desc; + struct vkd3d_shader_version version; + size_t token_count; + uint16_t magic; + + token_count = code_size / sizeof(*tx->start); + + if (token_count < 1) + { + vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_D3DBC_UNEXPECTED_EOF, + "Invalid shader size %zu (token count %zu). At least 2 tokens are required.", + code_size, token_count); + return VKD3D_ERROR_INVALID_SHADER; + } + + TRACE("Version: 0x%08x.\n", code[0]); + + magic = code[0] >> 16; + version.type = VKD3D_SHADER_TYPE_TEXTURE; + version.major = VKD3D_SM1_VERSION_MAJOR(code[0]); + version.minor = VKD3D_SM1_VERSION_MINOR(code[0]); + + if (magic != VKD3D_SM1_TX) + { + vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_D3DBC_INVALID_VERSION_TOKEN, + "Invalid shader magic %#x (token 0x%08x).", magic, code[0]); + return VKD3D_ERROR_INVALID_SHADER; + } + + if (version.major != 1 || version.minor != 0) + { + vkd3d_shader_error(message_context, &location, VKD3D_SHADER_ERROR_D3DBC_INVALID_VERSION_TOKEN, + "Invalid shader version %u.%u (token 0x%08x).", version.major, version.minor, code[0]); + return VKD3D_ERROR_INVALID_SHADER; + } + + tx->start = &code[1]; + tx->end = &code[token_count]; + tx->ptr = tx->start; + + shader_tx_read_sections(tx); + + tx->opcode_table = tx_opcode_table; + /* FXLC section */ + tx->start = tx->fxlc.start; + tx->end = tx->fxlc.end; + + token_count = tx->end - tx->start; + + /* Estimate instruction count to avoid reallocation in most shaders. */ + if (!vkd3d_shader_parser_init(&tx->p, message_context, compile_info->source_name, &version, &shader_tx_parser_ops, + code_size != ~(size_t)0 ? token_count / 4u + 4 : 16)) + return VKD3D_ERROR_OUT_OF_MEMORY; + shader_desc = &tx->p.shader_desc; + shader_desc->byte_code = code; + shader_desc->byte_code_size = code_size; + tx->ptr = tx->start; + + return VKD3D_OK; +} + static uint32_t get_external_constant_count(struct vkd3d_shader_sm1_parser *sm1, enum vkd3d_shader_d3dbc_constant_register set) { @@ -1363,6 +1581,247 @@ int vkd3d_shader_sm1_parser_create(const struct vkd3d_shader_compile_info *compi return VKD3D_OK; }
+struct fxlc_instruction +{ + uint32_t num_comp : 16; + uint32_t unused : 4; + uint32_t opcode : 11; + uint32_t scalar : 1; +}; + +static const struct vkd3d_fxlc_opcode_info *shader_tx_get_opcode_info( + const struct vkd3d_shader_tx_parser *tx, enum vkd3d_fxlc_opcode opcode) +{ + const struct vkd3d_fxlc_opcode_info *info; + unsigned int i = 0; + + for (;;) + { + info = &tx->opcode_table[i++]; + if (info->vkd3d_opcode == VKD3DSIH_INVALID) + return NULL; + + if (opcode == info->fxlc_opcode) + return info; + } +} + +enum fxlc_register_type +{ + VKD3DSPR_FXLC_IMMCONST = 1, + VKD3DSPR_FXLC_INPUT = 3, + VKD3DSPR_FXLC_RESULT = 4, + VKD3DSPR_FXLC_TEMP = 7, +}; + +static enum vkd3d_shader_register_type fxlc_get_register_type(uint32_t fxlc_regtable) +{ + static const enum vkd3d_shader_register_type map[] = + { + [VKD3DSPR_FXLC_INPUT ] = VKD3DSPR_INPUT, + [VKD3DSPR_FXLC_TEMP ] = VKD3DSPR_TEMP, + [VKD3DSPR_FXLC_RESULT ] = VKD3DSPR_COLOROUT, + [VKD3DSPR_FXLC_IMMCONST] = VKD3DSPR_IMMCONST, + }; + if (fxlc_regtable < ARRAY_SIZE(map)) return map[fxlc_regtable]; + FIXME("Unrecognized register table %u.\n", fxlc_regtable); + return VKD3DSPR_TEMP; +} + +static void shader_fxlc_read_src_param(struct vkd3d_shader_tx_parser *tx, + const struct fxlc_instruction *fxlc_ins, bool first_source, struct vkd3d_shader_src_param *src) +{ + bool scalar = first_source && fxlc_ins->scalar; + enum vkd3d_shader_register_type reg_type; + uint32_t flags, table, offset, swizzle; + const uint32_t **ptr = &tx->ptr; + unsigned int i; + + flags = read_u32(ptr); + if (flags) + { + vkd3d_shader_parser_error(&tx->p, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_INDEX, + "Relative addressing is not implemented for FXLC."); + return; + } + + table = read_u32(ptr); + offset = read_u32(ptr); + + reg_type = fxlc_get_register_type(table); + + vsir_register_init(&src->reg, reg_type, VKD3D_DATA_FLOAT, 1); + src->reg.idx[0].offset = offset / 4; + + if (src->reg.type == VKD3DSPR_IMMCONST) + { + for (i = 0; i < fxlc_ins->num_comp; ++i) + src->reg.u.immconst_float[i] = tx->clit.table[offset + (scalar ? 0 : i)]; + } + src->reg.dimension = VSIR_DIMENSION_VEC4; + + /* Components could only be specified consecutively. */ + swizzle = VKD3D_SHADER_NO_SWIZZLE; + swizzle >>= 8 * (offset % 4); + swizzle &= ~0u >> (8 * (4 - (scalar ? 1 : fxlc_ins->num_comp))); + + src->swizzle = swizzle; + src->modifiers = 0; +} + +static void shader_fxlc_read_dst_param(struct vkd3d_shader_tx_parser *tx, const struct fxlc_instruction *fxlc_ins, + struct vkd3d_shader_dst_param *dst) +{ + enum vkd3d_shader_register_type reg_type; + const uint32_t **ptr = &tx->ptr; + uint32_t flags, table, offset; + + flags = read_u32(ptr); + if (flags) + { + vkd3d_shader_parser_error(&tx->p, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_INDEX, + "Relative addressing is not implemented for FXLC."); + return; + } + table = read_u32(ptr); + offset = read_u32(ptr); + + reg_type = fxlc_get_register_type(table); + + vsir_register_init(&dst->reg, reg_type, VKD3D_DATA_FLOAT, 1); + dst->reg.idx[0].offset = offset / 4; + dst->reg.dimension = VSIR_DIMENSION_VEC4; + + dst->write_mask = ~0u >> (32 - fxlc_ins->num_comp); + dst->write_mask <<= offset % 4; + dst->modifiers = 0; + dst->shift = 0; +} + +static void shader_tx_read_instruction(struct vkd3d_shader_tx_parser *tx, struct vkd3d_shader_instruction *ins) +{ + const struct vkd3d_fxlc_opcode_info *opcode_info; + struct vkd3d_shader_src_param *src_params; + struct vkd3d_shader_dst_param *dst_param; + struct fxlc_instruction fxlc_ins; + const uint32_t **ptr = &tx->ptr; + uint32_t opcode_token; + unsigned int i; + + if (*ptr >= tx->end) + { + WARN("End of byte-code, failed to read opcode.\n"); + goto fail; + } + + ++tx->p.location.line; + opcode_token = read_u32(ptr); + memcpy(&fxlc_ins, &opcode_token, sizeof(opcode_token)); + + if (!(opcode_info = shader_tx_get_opcode_info(tx, fxlc_ins.opcode))) + { + vkd3d_shader_parser_error(&tx->p, VKD3D_SHADER_ERROR_D3DBC_INVALID_OPCODE, + "Invalid opcode %#x (token 0x%08x).", fxlc_ins.opcode, opcode_token); + goto fail; + } + + if (fxlc_ins.num_comp < 1 || fxlc_ins.num_comp > 4) + { + vkd3d_shader_parser_error(&tx->p, VKD3D_SHADER_ERROR_D3DBC_INVALID_OPCODE, + "Invalid component count %u (token 0x%08x).", fxlc_ins.num_comp, opcode_token); + goto fail; + } + + vsir_instruction_init(ins, &tx->p.location, opcode_info->vkd3d_opcode); + + ins->dst_count = 1; + ins->dst = dst_param = shader_parser_get_dst_params(&tx->p, ins->dst_count); + + ins->src_count = read_u32(ptr); + ins->src = src_params = shader_parser_get_src_params(&tx->p, ins->src_count); + + for (i = 0; i < ins->src_count; ++i) + shader_fxlc_read_src_param(tx, &fxlc_ins, i == 0, &src_params[i]); + + ins->dst_count = 1; + shader_fxlc_read_dst_param(tx, &fxlc_ins, dst_param); + + if (*ptr > tx->end) + { + vkd3d_shader_parser_error(&tx->p, VKD3D_SHADER_ERROR_D3DBC_UNEXPECTED_EOF, + "The current instruction ends %zu token(s) past the end of the shader.", + *ptr - tx->end); + goto fail; + } + + return; + +fail: + ins->handler_idx = VKD3DSIH_INVALID; + *ptr = tx->end; +} + +int vkd3d_shader_tx_parser_create(const struct vkd3d_shader_compile_info *compile_info, + struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser) +{ + struct vkd3d_shader_instruction_array *instructions; + struct vkd3d_shader_instruction *ins; + struct vkd3d_shader_tx_parser *tx; + uint32_t count; + unsigned int i; + int ret; + + if (!(tx = vkd3d_calloc(1, sizeof(*tx)))) + { + ERR("Failed to allocate parser.\n"); + return VKD3D_ERROR_OUT_OF_MEMORY; + } + + if ((ret = shader_tx_init(tx, compile_info, message_context)) < 0) + { + WARN("Failed to initialise shader parser, ret %d.\n", ret); + vkd3d_free(tx); + return ret; + } + + count = read_u32(&tx->ptr); + + instructions = &tx->p.instructions; + + if (!shader_instruction_array_reserve(instructions, count)) + { + ERR("Failed to allocate instructions.\n"); + vkd3d_shader_parser_error(&tx->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, "Out of memory."); + shader_tx_destroy(&tx->p); + return VKD3D_ERROR_OUT_OF_MEMORY; + } + + for (i = 0; i < count; ++i) + { + ins = &instructions->elements[instructions->count]; + shader_tx_read_instruction(tx, ins); + + if (ins->handler_idx == VKD3DSIH_INVALID) + { + WARN("Encountered unrecognized or invalid instruction.\n"); + shader_tx_destroy(&tx->p); + return VKD3D_ERROR_INVALID_SHADER; + } + ++instructions->count; + } + + if (tx->p.failed) + { + WARN("Failed to parse shader.\n"); + shader_tx_destroy(&tx->p); + return VKD3D_ERROR_INVALID_SHADER; + } + + *parser = &tx->p; + + return VKD3D_OK; +} + bool hlsl_sm1_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic, bool output, D3DSHADER_PARAM_REGISTER_TYPE *type, unsigned int *reg) { diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 052edeb50..894d5bd17 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -1451,6 +1451,30 @@ static int compile_d3d_bytecode(const struct vkd3d_shader_compile_info *compile_ return VKD3D_ERROR; }
+static int compile_tx_bytecode(const struct vkd3d_shader_compile_info *compile_info, + struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context) +{ + struct vkd3d_shader_parser *parser; + int ret; + + if ((ret = vkd3d_shader_tx_parser_create(compile_info, message_context, &parser)) < 0) + { + WARN("Failed to initialise shader parser.\n"); + return ret; + } + + vkd3d_shader_dump_shader(compile_info->source_type, parser->shader_version.type, &compile_info->source); + + if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_ASM) + { + ret = vkd3d_dxbc_binary_to_text(&parser->instructions, &parser->shader_version, compile_info, out); + vkd3d_shader_parser_destroy(parser); + return ret; + } + + return VKD3D_ERROR; +} + static int compile_dxbc_dxil(const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context) { @@ -1501,6 +1525,10 @@ int vkd3d_shader_compile(const struct vkd3d_shader_compile_info *compile_info, ret = compile_d3d_bytecode(compile_info, out, &message_context); break;
+ case VKD3D_SHADER_SOURCE_TX_BYTECODE: + ret = compile_tx_bytecode(compile_info, out, &message_context); + break; + case VKD3D_SHADER_SOURCE_DXBC_DXIL: ret = compile_dxbc_dxil(compile_info, out, &message_context); break; @@ -1685,6 +1713,7 @@ const enum vkd3d_shader_source_type *vkd3d_shader_get_supported_source_types(uns #ifdef VKD3D_SHADER_UNSUPPORTED_DXIL VKD3D_SHADER_SOURCE_DXBC_DXIL, #endif + VKD3D_SHADER_SOURCE_TX_BYTECODE, };
TRACE("count %p.\n", count); @@ -1719,6 +1748,11 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types( VKD3D_SHADER_TARGET_D3D_ASM, };
+ static const enum vkd3d_shader_target_type tx_types[] = + { + VKD3D_SHADER_TARGET_D3D_ASM, + }; + TRACE("source_type %#x, count %p.\n", source_type, count);
switch (source_type) @@ -1738,6 +1772,10 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types( *count = ARRAY_SIZE(d3dbc_types); return d3dbc_types;
+ case VKD3D_SHADER_SOURCE_TX_BYTECODE: + *count = ARRAY_SIZE(tx_types); + return tx_types; + default: *count = 0; return NULL; diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 2c84cb104..6627994b3 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -201,8 +201,12 @@ enum vkd3d_shader_error enum vkd3d_shader_opcode { VKD3DSIH_ABS, + VKD3DSIH_ACOS, VKD3DSIH_ADD, VKD3DSIH_AND, + VKD3DSIH_ASIN, + VKD3DSIH_ATAN, + VKD3DSIH_ATAN2, VKD3DSIH_ATOMIC_AND, VKD3DSIH_ATOMIC_CMP_STORE, VKD3DSIH_ATOMIC_IADD, @@ -227,6 +231,7 @@ enum vkd3d_shader_opcode VKD3DSIH_CND, VKD3DSIH_CONTINUE, VKD3DSIH_CONTINUEP, + VKD3DSIH_COS, VKD3DSIH_COUNTBITS, VKD3DSIH_CRS, VKD3DSIH_CUT, @@ -289,6 +294,8 @@ enum vkd3d_shader_opcode VKD3DSIH_DMOVC, VKD3DSIH_DMUL, VKD3DSIH_DNE, + VKD3DSIH_DOT, + VKD3DSIH_DOT_SWIZ, VKD3DSIH_DP2, VKD3DSIH_DP2ADD, VKD3DSIH_DP3, @@ -400,6 +407,9 @@ enum vkd3d_shader_opcode VKD3DSIH_MSAD, VKD3DSIH_MUL, VKD3DSIH_NE, + VKD3DSIH_NEG, + VKD3DSIH_NOISE, + VKD3DSIH_NOISE_SWIZ, VKD3DSIH_NOP, VKD3DSIH_NOT, VKD3DSIH_NRM, @@ -433,6 +443,7 @@ enum vkd3d_shader_opcode VKD3DSIH_SETP, VKD3DSIH_SGE, VKD3DSIH_SGN, + VKD3DSIH_SIN, VKD3DSIH_SINCOS, VKD3DSIH_SLT, VKD3DSIH_SQRT, @@ -1288,6 +1299,8 @@ void vkd3d_shader_trace_text_(const char *text, size_t size, const char *functio #define vkd3d_shader_trace_text(text, size) \ vkd3d_shader_trace_text_(text, size, __FUNCTION__)
+int vkd3d_shader_tx_parser_create(const struct vkd3d_shader_compile_info *compile_info, + struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser); int vkd3d_shader_sm1_parser_create(const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context, struct vkd3d_shader_parser **parser); int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compile_info, @@ -1495,8 +1508,10 @@ static inline void *vkd3d_find_struct_(const struct vkd3d_struct *chain, #define VKD3D_DXBC_CHUNK_ALIGNMENT sizeof(uint32_t)
#define TAG_AON9 VKD3D_MAKE_TAG('A', 'o', 'n', '9') +#define TAG_CLIT VKD3D_MAKE_TAG('C', 'L', 'I', 'T') #define TAG_DXBC VKD3D_MAKE_TAG('D', 'X', 'B', 'C') #define TAG_DXIL VKD3D_MAKE_TAG('D', 'X', 'I', 'L') +#define TAG_FXLC VKD3D_MAKE_TAG('F', 'X', 'L', 'C') #define TAG_ISG1 VKD3D_MAKE_TAG('I', 'S', 'G', '1') #define TAG_ISGN VKD3D_MAKE_TAG('I', 'S', 'G', 'N') #define TAG_OSG1 VKD3D_MAKE_TAG('O', 'S', 'G', '1') diff --git a/programs/vkd3d-compiler/main.c b/programs/vkd3d-compiler/main.c index 61e8d48a2..3df4f5be5 100644 --- a/programs/vkd3d-compiler/main.c +++ b/programs/vkd3d-compiler/main.c @@ -75,6 +75,9 @@ source_type_info[] = "d3dbc", "Legacy Direct3D byte-code.\n" " This is the format used for Direct3D shader model 1, 2, and 3 shaders.\n", true, VKD3D_SHADER_TARGET_SPIRV_BINARY}, + {VKD3D_SHADER_SOURCE_TX_BYTECODE, + "tx", "Texture shader byte-code.\n", + true, VKD3D_SHADER_TARGET_D3D_ASM}, {VKD3D_SHADER_SOURCE_DXBC_DXIL, "dxbc-dxil", "A 'DirectX Intermediate Language' shader embedded in a DXBC container.\n" " This is the format used for Direct3D shader model 6 shaders.\n", @@ -730,6 +733,8 @@ int main(int argc, char **argv) } else if ((token & 0xfffe0000) == 0xfffe0000) options.source_type = VKD3D_SHADER_SOURCE_D3D_BYTECODE; + else if (token == 0x54580100) + options.source_type = VKD3D_SHADER_SOURCE_TX_BYTECODE; else options.source_type = VKD3D_SHADER_SOURCE_HLSL; }