From: Zebediah Figura zfigura@codeweavers.com
--- include/vkd3d_shader.h | 45 +++- libs/vkd3d-shader/d3dbc.c | 258 +++++++++++++++++++++++ libs/vkd3d-shader/vkd3d_shader_private.h | 3 + tests/vkd3d_shader_api.c | 154 +++++++++++++- 4 files changed, 453 insertions(+), 7 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 5bc87945..a548fcf0 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -1556,7 +1556,8 @@ static inline uint32_t vkd3d_shader_create_swizzle(enum vkd3d_shader_swizzle_com }
/** - * A chained structure containing signatures scanned from a DXBC shader. + * A chained structure containing signatures scanned from a DXBC shader, or + * synthesized from legacy Direct3D bytecode instructions. * * All members (except for \ref type and \ref next) are output-only. * @@ -1566,6 +1567,48 @@ static inline uint32_t vkd3d_shader_create_swizzle(enum vkd3d_shader_swizzle_com * Members of this structure are allocated by vkd3d-shader and should be freed * with vkd3d_shader_free_scan_signature_info() when no longer needed. * + * Signature elements are synthesized from legacy Direct3D bytecode as follows: + * - The \ref vkd3d_shader_signature_element.semantic_name field is set to an + * uppercase string corresponding to the HLSL name for the usage, e.g. + * "POSITION", "BLENDWEIGHT", "COLOR", "PSIZE", etc. + * - The \ref vkd3d_shader_signature_element.semantic_index field is set to the + * usage index. + * - The \ref vkd3d_shader_signature_element.stream_index is always 0. + * - The \ref vkd3d_shader_signature_element.sysval_semantic field is set as + * follows: + * - For position outputs from vertex shaders, it is set to + * VKD3D_SHADER_SV_POSITION. + * - For shader model 3 pixel position inputs (i.e. VPOS, but not POSITION), + * it is set to VKD3D_SHADER_SV_POSITION. + * - For shader model 3 face inputs (i.e. VFACE), it is set to + * VKD3D_SHADER_SV_IS_FRONT_FACE. + * - For all other elements, it is set to VKD3D_SHADER_SV_NONE. + * - The \ref vkd3d_shader_signature_element.component_type field is always set + * to VKD3D_SHADER_COMPONENT_FLOAT. + * - The \ref vkd3d_shader_signature_element.register_index field is set to the + * bytecode register index. + * Note that for shader model 1 and 2 shaders (excepting vertex shader + * inputs), the register index of colour and texture coordinate registers will + * be equal to the usage index, and hence may not be unique. + * - The \ref vkd3d_shader_signature_element.mask field is set to the mask given + * in the DCL instruction, if one is present. If there is no DCL instruction + * for this semantic, it is set to the same value as the \ref used_mask field. + * For the scalar registers vFace, oDepth, oFog, and oPts, it is always 1. + * - The \ref vkd3d_shader_signature_element.used_mask field is set to the + * combined mask used by shader instructions (other than DCL). For scalar + * registers, it is always 1. + * - The \ref vkd3d_shader_signature_element.min_precision field is always + * VKD3D_SHADER_MINIMUM_PRECISION_NONE. + * + * Signature elements are synthesized for any input or output register declared + * or used in a legacy Direct3D bytecode shader, including the following: + * - Shader model 1 and 2 colour and texture coordinate registers. + * - The shader model 1 pixel shader output register. + * - Shader model 1 and 2 vertex shader output registers (position, fog, and + * point size). + * - Shader model 3 pixel shader system value input registers (pixel position + * and face). + * * \since 1.x */ struct vkd3d_shader_scan_signature_info diff --git a/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d-shader/d3dbc.c index 823df6f6..3fb4d06f 100644 --- a/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d-shader/d3dbc.c @@ -214,6 +214,8 @@ struct vkd3d_shader_sm1_parser bool abort;
struct vkd3d_shader_parser p; + + size_t input_signature_capacity, output_signature_capacity; };
/* This table is not order or position dependent. */ @@ -488,6 +490,245 @@ static void shader_sm1_parse_dst_param(uint32_t param, const struct vkd3d_shader dst->shift = (param & VKD3D_SM1_DSTSHIFT_MASK) >> VKD3D_SM1_DSTSHIFT_SHIFT; }
+static struct signature_element *find_signature_element(const struct shader_signature *signature, + const char *semantic_name, unsigned int semantic_index) +{ + struct signature_element *e = signature->elements; + unsigned int i; + + for (i = 0; i < signature->element_count; ++i) + { + if (!ascii_strcasecmp(e[i].semantic_name, semantic_name) + && e[i].semantic_index == semantic_index) + return &e[i]; + } + + return NULL; +} + +static struct signature_element *find_signature_element_by_register_index( + const struct shader_signature *signature, unsigned int register_index) +{ + struct signature_element *e = signature->elements; + unsigned int i; + + for (i = 0; i < signature->element_count; ++i) + { + if (e[i].register_index == register_index) + return &e[i]; + } + + return NULL; +} + +static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool output, + const char *name, unsigned int index, enum vkd3d_shader_sysval_semantic sysval, + unsigned int register_index, bool is_dcl, unsigned int mask) +{ + struct shader_signature *signature; + struct signature_element *element; + + if (output) + signature = &sm1->p.shader_desc.output_signature; + else + signature = &sm1->p.shader_desc.input_signature; + + if ((element = find_signature_element(signature, name, index))) + { + element->mask |= mask; + if (!is_dcl) + element->used_mask |= mask; + return true; + } + + if (!vkd3d_array_reserve((void **)&signature->elements, &signature->elements_capacity, + signature->element_count + 1, sizeof(*signature->elements))) + return false; + element = &signature->elements[signature->element_count++]; + + element->semantic_name = name; + element->semantic_index = index; + element->stream_index = 0; + element->sysval_semantic = sysval; + element->component_type = VKD3D_SHADER_COMPONENT_FLOAT; + element->register_index = register_index; + element->register_count = 1; + element->mask = mask; + element->used_mask = is_dcl ? 0 : mask; + element->min_precision = VKD3D_SHADER_MINIMUM_PRECISION_NONE; + + return true; +} + +static void add_signature_mask(struct vkd3d_shader_sm1_parser *sm1, bool output, + unsigned int register_index, unsigned int mask) +{ + struct shader_signature *signature; + struct signature_element *element; + + if (output) + signature = &sm1->p.shader_desc.output_signature; + else + signature = &sm1->p.shader_desc.input_signature; + + if (!(element = find_signature_element_by_register_index(signature, register_index))) + { + vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_UNDECLARED_SEMANTIC, + "%s register %u was used without being declared.", output ? "Output" : "Input", register_index); + return; + } + + element->used_mask |= mask; +} + +static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser *sm1, + const struct vkd3d_shader_register *reg, bool is_dcl, unsigned int mask) +{ + unsigned int register_index = reg->idx[0].offset; + + switch (reg->type) + { + case VKD3DSPR_TEMP: + if (sm1->p.shader_version.type == VKD3D_SHADER_TYPE_PIXEL + && sm1->p.shader_version.major == 1 && !register_index) + return add_signature_element(sm1, true, "COLOR", 0, VKD3D_SHADER_SV_NONE, 0, is_dcl, mask); + return true; + + case VKD3DSPR_INPUT: + /* For vertex shaders or sm3 pixel shaders, we should have already + * had a DCL instruction. Otherwise, this is a colour input. */ + if (sm1->p.shader_version.type == VKD3D_SHADER_TYPE_VERTEX || sm1->p.shader_version.major == 3) + { + add_signature_mask(sm1, false, register_index, mask); + return true; + } + return add_signature_element(sm1, false, "COLOR", register_index, + VKD3D_SHADER_SV_NONE, register_index, is_dcl, mask); + + case VKD3DSPR_TEXTURE: + /* For vertex shaders, this is ADDR. */ + if (sm1->p.shader_version.type == VKD3D_SHADER_TYPE_VERTEX) + return true; + return add_signature_element(sm1, false, "TEXCOORD", register_index, + VKD3D_SHADER_SV_NONE, register_index, is_dcl, mask); + + case VKD3DSPR_OUTPUT: + if (sm1->p.shader_version.type == VKD3D_SHADER_TYPE_VERTEX) + { + /* For sm < 2 vertex shaders, this is TEXCRDOUT. + * + * For sm3 vertex shaders, this is OUTPUT, but we already + * should have had a DCL instruction. */ + if (sm1->p.shader_version.major == 3) + { + add_signature_mask(sm1, true, register_index, mask); + return true; + } + return add_signature_element(sm1, true, "TEXCOORD", register_index, + VKD3D_SHADER_SV_NONE, register_index, is_dcl, mask); + } + /* fall through */ + + case VKD3DSPR_ATTROUT: + case VKD3DSPR_COLOROUT: + return add_signature_element(sm1, true, "COLOR", register_index, + VKD3D_SHADER_SV_NONE, register_index, is_dcl, mask); + + case VKD3DSPR_DEPTHOUT: + return add_signature_element(sm1, true, "DEPTH", 0, + VKD3D_SHADER_SV_NONE, register_index, is_dcl, 0x1); + + case VKD3DSPR_RASTOUT: + switch (register_index) + { + case 0: + return add_signature_element(sm1, true, "POSITION", 0, + VKD3D_SHADER_SV_POSITION, register_index, is_dcl, mask); + + case 1: + return add_signature_element(sm1, true, "FOG", 0, + VKD3D_SHADER_SV_NONE, register_index, is_dcl, 0x1); + + case 2: + return add_signature_element(sm1, true, "PSIZE", 0, + VKD3D_SHADER_SV_NONE, register_index, is_dcl, 0x1); + + default: + vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_INDEX, + "Invalid rasterizer output index %u.", register_index); + return true; + } + + case VKD3DSPR_MISCTYPE: + switch (register_index) + { + case 0: + return add_signature_element(sm1, false, "VPOS", 0, + VKD3D_SHADER_SV_POSITION, register_index, is_dcl, mask); + + case 1: + return add_signature_element(sm1, false, "VFACE", 0, + VKD3D_SHADER_SV_IS_FRONT_FACE, register_index, is_dcl, 0x1); + + default: + vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_INDEX, + "Invalid miscellaneous fragment input index %u.", register_index); + return true; + } + + default: + return true; + } +} + +static bool add_signature_element_from_semantic(struct vkd3d_shader_sm1_parser *sm1, + const struct vkd3d_shader_semantic *semantic) +{ + const struct vkd3d_shader_register *reg = &semantic->resource.reg.reg; + enum vkd3d_shader_sysval_semantic sysval = VKD3D_SHADER_SV_NONE; + unsigned int mask = semantic->resource.reg.write_mask; + bool output; + + static const char sm1_semantic_names[][13] = + { + [VKD3D_DECL_USAGE_POSITION ] = "POSITION", + [VKD3D_DECL_USAGE_BLEND_WEIGHT ] = "BLENDWEIGHT", + [VKD3D_DECL_USAGE_BLEND_INDICES] = "BLENDINDICES", + [VKD3D_DECL_USAGE_NORMAL ] = "NORMAL", + [VKD3D_DECL_USAGE_PSIZE ] = "PSIZE", + [VKD3D_DECL_USAGE_TEXCOORD ] = "TEXCOORD", + [VKD3D_DECL_USAGE_TANGENT ] = "TANGENT", + [VKD3D_DECL_USAGE_BINORMAL ] = "BINORMAL", + [VKD3D_DECL_USAGE_TESS_FACTOR ] = "TESSFACTOR", + [VKD3D_DECL_USAGE_POSITIONT ] = "POSITIONT", + [VKD3D_DECL_USAGE_COLOR ] = "COLOR", + [VKD3D_DECL_USAGE_FOG ] = "FOG", + [VKD3D_DECL_USAGE_DEPTH ] = "DEPTH", + [VKD3D_DECL_USAGE_SAMPLE ] = "SAMPLE", + }; + + if (reg->type == VKD3DSPR_OUTPUT) + output = true; + else if (reg->type == VKD3DSPR_INPUT || reg->type == VKD3DSPR_TEXTURE) + output = false; + else /* vpos and vface don't have a semantic. */ + return add_signature_element_from_register(sm1, reg, true, mask); + + /* sm2 pixel shaders use DCL but don't provide a semantic. */ + if (sm1->p.shader_version.type == VKD3D_SHADER_TYPE_PIXEL && sm1->p.shader_version.major == 2) + return add_signature_element_from_register(sm1, reg, true, mask); + + /* With the exception of vertex POSITION output, none of these are system + * values. Pixel POSITION input is not equivalent to SV_Position; the closer + * equivalent is VPOS, which is not declared as a semantic. */ + if (sm1->p.shader_version.type == VKD3D_SHADER_TYPE_VERTEX + && output && semantic->usage == VKD3D_DECL_USAGE_POSITION) + sysval = VKD3D_SHADER_SV_POSITION; + + return add_signature_element(sm1, output, sm1_semantic_names[semantic->usage], + semantic->usage_idx, sysval, reg->idx[0].offset, true, mask); +} + /* Read a parameter token from the input stream, and possibly a relative * addressing token. */ static void shader_sm1_read_param(struct vkd3d_shader_sm1_parser *sm1, @@ -638,6 +879,8 @@ static void shader_sm1_read_semantic(struct vkd3d_shader_sm1_parser *sm1, range = &semantic->resource.range; range->space = 0; range->first = range->last = semantic->resource.reg.reg.idx[0].offset; + + add_signature_element_from_semantic(sm1, semantic); }
static void shader_sm1_read_immconst(struct vkd3d_shader_sm1_parser *sm1, const uint32_t **ptr, @@ -741,6 +984,14 @@ static void shader_sm1_validate_instruction(struct vkd3d_shader_sm1_parser *sm1, } }
+static unsigned int mask_from_swizzle(unsigned int swizzle) +{ + return (1u << vkd3d_swizzle_get_component(swizzle, 0)) + | (1u << vkd3d_swizzle_get_component(swizzle, 1)) + | (1u << vkd3d_swizzle_get_component(swizzle, 2)) + | (1u << vkd3d_swizzle_get_component(swizzle, 3)); +} + static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, struct vkd3d_shader_instruction *ins) { struct vkd3d_shader_src_param *src_params, *predicate; @@ -829,7 +1080,10 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str { /* Destination token */ if (ins->dst_count) + { shader_sm1_read_dst_param(sm1, &p, dst_param); + add_signature_element_from_register(sm1, &dst_param->reg, false, dst_param->write_mask); + }
/* Predication token */ if (ins->predicate) @@ -837,7 +1091,11 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str
/* Other source tokens */ for (i = 0; i < ins->src_count; ++i) + { shader_sm1_read_src_param(sm1, &p, &src_params[i]); + add_signature_element_from_register(sm1, &src_params[i].reg, + false, mask_from_swizzle(src_params[i].swizzle)); + } }
if (sm1->abort) diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index f1641c1e..5d830e08 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -137,6 +137,8 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_D3DBC_INVALID_OPCODE = 7002, VKD3D_SHADER_ERROR_D3DBC_INVALID_RESOURCE_TYPE = 7003, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY = 7004, + VKD3D_SHADER_ERROR_D3DBC_INVALID_REGISTER_INDEX = 7005, + VKD3D_SHADER_ERROR_D3DBC_UNDECLARED_SEMANTIC = 7006,
VKD3D_SHADER_WARNING_D3DBC_IGNORED_INSTRUCTION_FLAGS= 7300, }; @@ -792,6 +794,7 @@ struct signature_element struct shader_signature { struct signature_element *elements; + size_t elements_capacity; unsigned int element_count; };
diff --git a/tests/vkd3d_shader_api.c b/tests/vkd3d_shader_api.c index 318e5068..f9a3f717 100644 --- a/tests/vkd3d_shader_api.c +++ b/tests/vkd3d_shader_api.c @@ -476,6 +476,75 @@ static void test_scan_signatures(void) {"position", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 0, 0xf, 0xf}, };
+ static const char vs3_source[] = + "void main(\n" + " in float4 c : position,\n" + " out float4 b : position,\n" + " in float4 a : binormal,\n" + " in float4 d : blendindices,\n" + " inout float4 e : texcoord2,\n" + " inout float4 f : color,\n" + " inout float g : fog,\n" + " inout float h : psize)\n" + "{\n" + " b = a + c + d;\n" + "}"; + + static const struct vkd3d_shader_signature_element vs3_inputs[] = + { + {"POSITION", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 0, 0xf, 0xf}, + {"BINORMAL", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 1, 0xf, 0xf}, + {"BLENDINDICES", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 2, 0xf, 0xf}, + {"TEXCOORD", 2, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 3, 0xf, 0xf}, + {"COLOR", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 4, 0xf, 0xf}, + {"FOG", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 5, 0xf, 0xf}, + {"PSIZE", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 6, 0xf, 0xf}, + }; + + static const struct vkd3d_shader_signature_element vs3_outputs[] = + { + {"POSITION", 0, 0, VKD3D_SHADER_SV_POSITION, VKD3D_SHADER_COMPONENT_FLOAT, 0, 0xf, 0xf}, + {"TEXCOORD", 2, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 2, 0xf, 0xf}, + {"COLOR", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 0, 0xf, 0xf}, + {"FOG", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 1, 0x1, 0x1}, + {"PSIZE", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 2, 0x1, 0x1}, + }; + + static const char vs4_source[] = + "void main(\n" + " inout float4 c : position,\n" + " inout float4 a : binormal,\n" + " inout float4 d : blendindices,\n" + " inout float4 e : texcoord2,\n" + " inout float4 f : color,\n" + " inout float4 g : fog,\n" + " inout float h : psize)\n" + "{\n" + "}"; + + static const struct vkd3d_shader_signature_element vs4_inputs[] = + { + {"POSITION", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 0, 0xf, 0xf}, + {"BINORMAL", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 1, 0xf, 0xf}, + {"BLENDINDICES", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 2, 0xf, 0xf}, + {"TEXCOORD", 2, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 3, 0xf, 0xf}, + {"COLOR", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 4, 0xf, 0xf}, + {"FOG", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 5, 0xf, 0xf}, + {"PSIZE", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 6, 0xf, 0xf}, + }; + + static const struct vkd3d_shader_signature_element vs4_outputs[] = + { + {"POSITION", 0, 0, VKD3D_SHADER_SV_POSITION, VKD3D_SHADER_COMPONENT_FLOAT, 0, 0xf, 0xf}, + {"BINORMAL", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 1, 0xf, 0xf}, + {"BLENDINDICES", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 2, 0xf, 0xf}, + {"TEXCOORD", 2, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 3, 0xf, 0xf}, + {"COLOR", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 4, 0xf, 0xf}, + {"FOG", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 5, 0xf, 0xf}, + /* FIXME: This doesn't match native, which always declares and writes all 4 components. */ + {"PSIZE", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 6, 0x1, 0x1}, + }; + static const char ps1_source[] = "void main(\n" " in float2 a : apple,\n" @@ -501,6 +570,72 @@ static void test_scan_signatures(void) {"sv_depth", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, ~0u, 0x1, 0x1}, };
+ static const char ps2_source[] = + "void main(\n" + "in float4 c : color,\n" + "in float4 a : texcoord2,\n" + "out float4 b : color)\n" + "{\n" + "b = a.x + c;\n" + "}"; + + static const struct vkd3d_shader_signature_element ps2_inputs[] = + { + {"TEXCOORD", 2, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 2, 0xf, 0xf}, + {"COLOR", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 0, 0xf, 0xf}, + }; + + static const struct vkd3d_shader_signature_element ps2_outputs[] = + { + {"COLOR", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 0, 0xf, 0xf}, + }; + + static const char ps3_source[] = + "void main(\n" + "in float4 c : color,\n" + "in float4 a : texcoord2,\n" + "out float4 b : color,\n" + "out float d : depth)\n" + "{\n" + "b = c;\n" + "d = a;\n" + "}"; + + static const struct vkd3d_shader_signature_element ps3_inputs[] = + { + {"COLOR", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 0, 0xf, 0xf}, + {"TEXCOORD", 2, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 2, 0xf, 0xf}, + }; + + static const struct vkd3d_shader_signature_element ps3_outputs[] = + { + {"COLOR", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 0, 0xf, 0xf}, + {"DEPTH", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 0, 0x1, 0x1}, + }; + + static const char ps4_source[] = + "void main(\n" + " in float4 c : color,\n" + " in float4 a : texcoord2,\n" + " out float4 b : color,\n" + " inout float d : depth,\n" + " in float4 e : blendindices,\n" + " in float4 f : vpos,\n" + " in float g : vface)\n" + "{\n" + " b = c + a + e + f + g;\n" + "}"; + + static const struct vkd3d_shader_signature_element ps4_inputs[] = + { + {"COLOR", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 0, 0xf, 0xf}, + {"TEXCOORD", 2, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 1, 0xf, 0xf}, + {"DEPTH", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 2, 0xf, 0xf}, + {"BLENDINDICES", 0, 0, VKD3D_SHADER_SV_NONE, VKD3D_SHADER_COMPONENT_FLOAT, 3, 0xf, 0xf}, + {"VPOS", 0, 0, VKD3D_SHADER_SV_POSITION, VKD3D_SHADER_COMPONENT_FLOAT, 0, 0xf, 0xf}, + {"VFACE", 0, 0, VKD3D_SHADER_SV_IS_FRONT_FACE, VKD3D_SHADER_COMPONENT_FLOAT, 1, 0x1, 0x1}, + }; + static const char cs1_source[] = "[numthreads(1, 1, 1)]\n" "void main(\n" @@ -513,6 +648,7 @@ static void test_scan_signatures(void) static const struct { const char *source; + bool sm4; const char *profile; const struct vkd3d_shader_signature_element *inputs; size_t input_count; @@ -523,10 +659,16 @@ static void test_scan_signatures(void) } tests[] = { - {vs1_source, "vs_4_0", vs1_inputs, ARRAY_SIZE(vs1_inputs), vs1_outputs, ARRAY_SIZE(vs1_outputs)}, - {vs2_source, "vs_4_0", vs2_inputs, ARRAY_SIZE(vs2_inputs), vs2_outputs, ARRAY_SIZE(vs2_outputs)}, - {ps1_source, "ps_4_0", ps1_inputs, ARRAY_SIZE(ps1_inputs), ps1_outputs, ARRAY_SIZE(ps1_outputs)}, - {cs1_source, "cs_5_0", NULL, 0, NULL, 0}, + {vs1_source, true, "vs_4_0", vs1_inputs, ARRAY_SIZE(vs1_inputs), vs1_outputs, ARRAY_SIZE(vs1_outputs)}, + {vs2_source, true, "vs_4_0", vs2_inputs, ARRAY_SIZE(vs2_inputs), vs2_outputs, ARRAY_SIZE(vs2_outputs)}, + {vs3_source, false, "vs_1_1", vs3_inputs, ARRAY_SIZE(vs3_inputs), vs3_outputs, ARRAY_SIZE(vs3_outputs)}, + {vs3_source, false, "vs_2_0", vs3_inputs, ARRAY_SIZE(vs3_inputs), vs3_outputs, ARRAY_SIZE(vs3_outputs)}, + {vs4_source, false, "vs_3_0", vs4_inputs, ARRAY_SIZE(vs4_inputs), vs4_outputs, ARRAY_SIZE(vs4_outputs)}, + {ps1_source, true, "ps_4_0", ps1_inputs, ARRAY_SIZE(ps1_inputs), ps1_outputs, ARRAY_SIZE(ps1_outputs)}, + {ps2_source, false, "ps_1_1", ps2_inputs, ARRAY_SIZE(ps2_inputs), ps2_outputs, ARRAY_SIZE(ps2_outputs)}, + {ps3_source, false, "ps_2_0", ps3_inputs, ARRAY_SIZE(ps3_inputs), ps3_outputs, ARRAY_SIZE(ps3_outputs)}, + {ps4_source, false, "ps_3_0", ps4_inputs, ARRAY_SIZE(ps4_inputs), ps3_outputs, ARRAY_SIZE(ps3_outputs)}, + {cs1_source, true, "cs_5_0", NULL, 0, NULL, 0}, };
for (i = 0; i < ARRAY_SIZE(tests); ++i) @@ -536,7 +678,7 @@ static void test_scan_signatures(void) compile_info.source.code = tests[i].source; compile_info.source.size = strlen(tests[i].source); compile_info.source_type = VKD3D_SHADER_SOURCE_HLSL; - compile_info.target_type = VKD3D_SHADER_TARGET_DXBC_TPF; + compile_info.target_type = tests[i].sm4 ? VKD3D_SHADER_TARGET_DXBC_TPF : VKD3D_SHADER_TARGET_D3D_BYTECODE; compile_info.log_level = VKD3D_SHADER_LOG_INFO;
compile_info.next = &hlsl_info; @@ -545,7 +687,7 @@ static void test_scan_signatures(void) rc = vkd3d_shader_compile(&compile_info, &dxbc, NULL); ok(rc == VKD3D_OK, "Got unexpected error code %d.\n", rc);
- compile_info.source_type = VKD3D_SHADER_SOURCE_DXBC_TPF; + compile_info.source_type = tests[i].sm4 ? VKD3D_SHADER_SOURCE_DXBC_TPF : VKD3D_SHADER_SOURCE_D3D_BYTECODE; compile_info.source = dxbc;
compile_info.next = &signature_info;