vkd3d-shader/ir: Store the shader version in struct vsir_program.

This commit is contained in:
Henri Verbeet 2024-01-16 16:40:30 +01:00 committed by Alexandre Julliard
parent fc9043be3c
commit 23dcd4f22b
Notes: Alexandre Julliard 2024-01-22 22:53:09 +01:00
Approved-by: Alexandre Julliard (@julliard)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/585
8 changed files with 61 additions and 56 deletions

View File

@ -2017,10 +2017,11 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler,
shader_addline(buffer, "\n");
}
enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instruction_array *instructions,
const struct vkd3d_shader_version *shader_version, const struct vkd3d_shader_compile_info *compile_info,
enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program,
const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_code *out, enum vsir_asm_dialect dialect)
{
const struct vkd3d_shader_version *shader_version = &program->shader_version;
enum vkd3d_shader_compile_option_formatting_flags formatting;
struct vkd3d_d3d_asm_compiler compiler =
{
@ -2089,9 +2090,9 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instructio
shader_version->minor, compiler.colours.reset);
indent = 0;
for (i = 0; i < instructions->count; ++i)
for (i = 0; i < program->instructions.count; ++i)
{
struct vkd3d_shader_instruction *ins = &instructions->elements[i];
struct vkd3d_shader_instruction *ins = &program->instructions.elements[i];
switch (ins->handler_idx)
{
@ -2145,13 +2146,12 @@ enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instructio
return result;
}
void vkd3d_shader_trace(const struct vkd3d_shader_instruction_array *instructions,
const struct vkd3d_shader_version *shader_version)
void vkd3d_shader_trace(const struct vsir_program *program)
{
const char *p, *q, *end;
struct vkd3d_shader_code code;
if (vkd3d_dxbc_binary_to_text(instructions, shader_version, NULL, &code, VSIR_ASM_VSIR) != VKD3D_OK)
if (vkd3d_dxbc_binary_to_text(program, NULL, &code, VSIR_ASM_VSIR) != VKD3D_OK)
return;
end = (const char *)code.code + code.size;

View File

@ -414,6 +414,7 @@ static bool has_relative_address(uint32_t param)
static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info(
const struct vkd3d_shader_sm1_parser *sm1, enum vkd3d_sm1_opcode opcode)
{
const struct vkd3d_shader_version *version = &sm1->p.program.shader_version;
const struct vkd3d_sm1_opcode_info *info;
unsigned int i = 0;
@ -424,8 +425,8 @@ static const struct vkd3d_sm1_opcode_info *shader_sm1_get_opcode_info(
return NULL;
if (opcode == info->sm1_opcode
&& vkd3d_shader_ver_ge(&sm1->p.shader_version, info->min_version.major, info->min_version.minor)
&& (vkd3d_shader_ver_le(&sm1->p.shader_version, info->max_version.major, info->max_version.minor)
&& vkd3d_shader_ver_ge(version, info->min_version.major, info->min_version.minor)
&& (vkd3d_shader_ver_le(version, info->max_version.major, info->max_version.minor)
|| !info->max_version.major))
return info;
}
@ -567,7 +568,7 @@ static bool add_signature_element(struct vkd3d_shader_sm1_parser *sm1, bool outp
element->register_count = 1;
element->mask = mask;
element->used_mask = is_dcl ? 0 : mask;
if (sm1->p.shader_version.type == VKD3D_SHADER_TYPE_PIXEL && !output)
if (sm1->p.program.shader_version.type == VKD3D_SHADER_TYPE_PIXEL && !output)
element->interpolation_mode = VKD3DSIM_LINEAR;
return true;
@ -597,20 +598,20 @@ static void add_signature_mask(struct vkd3d_shader_sm1_parser *sm1, bool output,
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)
{
const struct vkd3d_shader_version *version = &sm1->p.program.shader_version;
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)
if (version->type == VKD3D_SHADER_TYPE_PIXEL && version->major == 1 && !register_index)
return add_signature_element(sm1, true, "COLOR", 0, VKD3D_SHADER_SV_TARGET, 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)
if (version->type == VKD3D_SHADER_TYPE_VERTEX || version->major == 3)
{
add_signature_mask(sm1, false, register_index, mask);
return true;
@ -620,19 +621,19 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser *
case VKD3DSPR_TEXTURE:
/* For vertex shaders, this is ADDR. */
if (sm1->p.shader_version.type == VKD3D_SHADER_TYPE_VERTEX)
if (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)
if (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)
if (version->major == 3)
{
add_signature_mask(sm1, true, register_index, mask);
return true;
@ -700,6 +701,7 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser *
static bool add_signature_element_from_semantic(struct vkd3d_shader_sm1_parser *sm1,
const struct vkd3d_shader_semantic *semantic)
{
const struct vkd3d_shader_version *version = &sm1->p.program.shader_version;
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;
@ -731,13 +733,13 @@ static bool add_signature_element_from_semantic(struct vkd3d_shader_sm1_parser *
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)
if (version->type == VKD3D_SHADER_TYPE_PIXEL && 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
if (version->type == VKD3D_SHADER_TYPE_VERTEX
&& output && semantic->usage == VKD3D_DECL_USAGE_POSITION)
sysval = VKD3D_SHADER_SV_POSITION;
@ -824,7 +826,7 @@ static void shader_sm1_read_param(struct vkd3d_shader_sm1_parser *sm1,
* VS >= 2.0 have relative addressing (with token)
* VS >= 1.0 < 2.0 have relative addressing (without token)
* The version check below should work in general. */
if (sm1->p.shader_version.major < 2)
if (sm1->p.program.shader_version.major < 2)
{
*addr_token = (1u << 31)
| ((VKD3DSPR_ADDR << VKD3D_SM1_REGISTER_TYPE_SHIFT2) & VKD3D_SM1_REGISTER_TYPE_MASK2)
@ -853,7 +855,7 @@ static void shader_sm1_skip_opcode(const struct vkd3d_shader_sm1_parser *sm1, co
/* Version 2.0+ shaders may contain address tokens, but fortunately they
* have a useful length mask - use it here. Version 1.x shaders contain no
* such tokens. */
if (sm1->p.shader_version.major >= 2)
if (sm1->p.program.shader_version.major >= 2)
{
length = (opcode_token & VKD3D_SM1_INSTRUCTION_LENGTH_MASK) >> VKD3D_SM1_INSTRUCTION_LENGTH_SHIFT;
*ptr += length;
@ -1109,7 +1111,7 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str
vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_INVALID_OPCODE,
"Invalid opcode %#x (token 0x%08x, shader version %u.%u).",
opcode_token & VKD3D_SM1_OPCODE_MASK, opcode_token,
sm1->p.shader_version.major, sm1->p.shader_version.minor);
sm1->p.program.shader_version.major, sm1->p.program.shader_version.minor);
goto fail;
}

View File

@ -6639,9 +6639,9 @@ static enum vkd3d_result sm6_parser_emit_thread_group(struct sm6_parser *sm6, co
unsigned int group_sizes[3];
unsigned int i;
if (sm6->p.shader_version.type != VKD3D_SHADER_TYPE_COMPUTE)
if (sm6->p.program.shader_version.type != VKD3D_SHADER_TYPE_COMPUTE)
{
WARN("Shader of type %#x has thread group dimensions.\n", sm6->p.shader_version.type);
WARN("Shader of type %#x has thread group dimensions.\n", sm6->p.program.shader_version.type);
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES,
"Shader has thread group dimensions but is not a compute shader.");
return VKD3D_ERROR_INVALID_SHADER;

View File

@ -18,8 +18,9 @@
#include "vkd3d_shader_private.h"
bool vsir_program_init(struct vsir_program *program, unsigned int reserve)
bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_version *version, unsigned int reserve)
{
program->shader_version = *version;
return shader_instruction_array_init(&program->instructions, reserve);
}
@ -1245,8 +1246,8 @@ static enum vkd3d_result shader_normalise_io_registers(struct vkd3d_shader_parse
unsigned int i, j;
normaliser.phase = VKD3DSIH_INVALID;
normaliser.shader_type = parser->shader_version.type;
normaliser.major = parser->shader_version.major;
normaliser.shader_type = parser->program.shader_version.type;
normaliser.major = parser->program.shader_version.major;
normaliser.input_signature = &parser->shader_desc.input_signature;
normaliser.output_signature = &parser->shader_desc.output_signature;
normaliser.patch_constant_signature = &parser->shader_desc.patch_constant_signature;
@ -1878,11 +1879,12 @@ static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flatte
bool main_block_open, is_hull_shader, after_declarations_section;
struct vkd3d_shader_parser *parser = flattener->parser;
struct vkd3d_shader_instruction_array *instructions;
struct vsir_program *program = &parser->program;
struct vkd3d_shader_instruction *dst_ins;
size_t i;
instructions = &parser->program.instructions;
is_hull_shader = parser->shader_version.type == VKD3D_SHADER_TYPE_HULL;
instructions = &program->instructions;
is_hull_shader = program->shader_version.type == VKD3D_SHADER_TYPE_HULL;
main_block_open = !is_hull_shader;
after_declarations_section = is_hull_shader;
@ -2257,11 +2259,11 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser,
if (parser->shader_desc.is_dxil)
return result;
if (parser->shader_version.type != VKD3D_SHADER_TYPE_PIXEL
if (parser->program.shader_version.type != VKD3D_SHADER_TYPE_PIXEL
&& (result = remap_output_signature(parser, compile_info)) < 0)
return result;
if (parser->shader_version.type == VKD3D_SHADER_TYPE_HULL
if (parser->program.shader_version.type == VKD3D_SHADER_TYPE_HULL
&& (result = instruction_array_flatten_hull_shader_phases(instructions)) >= 0)
{
result = instruction_array_normalise_hull_shader_control_point_io(instructions,
@ -2283,7 +2285,7 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser,
result = normalise_combined_samplers(parser);
if (result >= 0 && TRACE_ON())
vkd3d_shader_trace(instructions, &parser->shader_version);
vkd3d_shader_trace(&parser->program);
if (result >= 0 && !parser->failed)
result = vsir_validate(parser);
@ -2297,6 +2299,7 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser,
struct validation_context
{
struct vkd3d_shader_parser *parser;
const struct vsir_program *program;
size_t instruction_idx;
bool invalid_instruction_idx;
bool dcl_temps_found;
@ -2364,7 +2367,7 @@ static void vsir_validate_register(struct validation_context *ctx,
unsigned int i, temp_count = ctx->temp_count;
/* SM1-3 shaders do not include a DCL_TEMPS instruction. */
if (ctx->parser->shader_version.major <= 3)
if (ctx->program->shader_version.major <= 3)
temp_count = ctx->parser->shader_desc.temp_count;
if (reg->type >= VKD3DSPR_COUNT)
@ -2712,10 +2715,11 @@ static void vsir_validate_cf_type(struct validation_context *ctx,
static void vsir_validate_instruction(struct validation_context *ctx)
{
const struct vkd3d_shader_version *version = &ctx->program->shader_version;
const struct vkd3d_shader_instruction *instruction;
size_t i;
instruction = &ctx->parser->program.instructions.elements[ctx->instruction_idx];
instruction = &ctx->program->instructions.elements[ctx->instruction_idx];
ctx->parser->location = instruction->location;
for (i = 0; i < instruction->dst_count; ++i)
@ -2738,7 +2742,7 @@ static void vsir_validate_instruction(struct validation_context *ctx)
case VKD3DSIH_HS_JOIN_PHASE:
vsir_validate_dst_count(ctx, instruction, 0);
vsir_validate_src_count(ctx, instruction, 0);
if (ctx->parser->shader_version.type != VKD3D_SHADER_TYPE_HULL)
if (version->type != VKD3D_SHADER_TYPE_HULL)
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, "Phase instruction %#x is only valid in a hull shader.",
instruction->handler_idx);
if (ctx->depth != 0)
@ -2753,9 +2757,9 @@ static void vsir_validate_instruction(struct validation_context *ctx)
break;
}
if (ctx->parser->shader_version.type == VKD3D_SHADER_TYPE_HULL &&
ctx->phase == VKD3DSIH_INVALID)
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, "Instruction %#x appear before any phase instruction in a hull shader.",
if (version->type == VKD3D_SHADER_TYPE_HULL && ctx->phase == VKD3DSIH_INVALID)
validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER,
"Instruction %#x appear before any phase instruction in a hull shader.",
instruction->handler_idx);
/* We support two different control flow types in shaders:
@ -2830,7 +2834,7 @@ static void vsir_validate_instruction(struct validation_context *ctx)
case VKD3DSIH_LOOP:
vsir_validate_cf_type(ctx, instruction, CF_TYPE_STRUCTURED);
vsir_validate_dst_count(ctx, instruction, 0);
vsir_validate_src_count(ctx, instruction, ctx->parser->shader_version.major <= 3 ? 2 : 0);
vsir_validate_src_count(ctx, instruction, version->major <= 3 ? 2 : 0);
if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks)))
return;
ctx->blocks[ctx->depth++] = instruction->handler_idx;
@ -2991,6 +2995,7 @@ enum vkd3d_result vsir_validate(struct vkd3d_shader_parser *parser)
struct validation_context ctx =
{
.parser = parser,
.program = &parser->program,
.phase = VKD3DSIH_INVALID,
};
unsigned int i;

View File

@ -9810,7 +9810,7 @@ int spirv_compile(struct vkd3d_shader_parser *parser,
struct spirv_compiler *spirv_compiler;
int ret;
if (!(spirv_compiler = spirv_compiler_create(&parser->shader_version, &parser->shader_desc,
if (!(spirv_compiler = spirv_compiler_create(&parser->program.shader_version, &parser->shader_desc,
compile_info, scan_descriptor_info, message_context, &parser->location, parser->config_flags)))
{
ERR("Failed to create SPIR-V compiler.\n");

View File

@ -711,7 +711,7 @@ static struct vkd3d_shader_sm4_parser *vkd3d_shader_sm4_parser(struct vkd3d_shad
static bool shader_is_sm_5_1(const struct vkd3d_shader_sm4_parser *sm4)
{
const struct vkd3d_shader_version *version = &sm4->p.shader_version;
const struct vkd3d_shader_version *version = &sm4->p.program.shader_version;
return version->major >= 5 && version->minor >= 1;
}
@ -2020,7 +2020,7 @@ static bool register_is_control_point_input(const struct vkd3d_shader_register *
{
return reg->type == VKD3DSPR_INCONTROLPOINT || reg->type == VKD3DSPR_OUTCONTROLPOINT
|| (reg->type == VKD3DSPR_INPUT && (priv->phase == VKD3DSIH_HS_CONTROL_POINT_PHASE
|| priv->p.shader_version.type == VKD3D_SHADER_TYPE_GEOMETRY));
|| priv->p.program.shader_version.type == VKD3D_SHADER_TYPE_GEOMETRY));
}
static uint32_t mask_from_swizzle(uint32_t swizzle)
@ -2662,7 +2662,7 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi
/* DXBC stores used masks inverted for output signatures, for some reason.
* We return them un-inverted. */
uninvert_used_masks(&shader_desc->output_signature);
if (sm4->p.shader_version.type == VKD3D_SHADER_TYPE_HULL)
if (sm4->p.program.shader_version.type == VKD3D_SHADER_TYPE_HULL)
uninvert_used_masks(&shader_desc->patch_constant_signature);
if (!shader_sm4_parser_validate_signature(sm4, &shader_desc->input_signature,
@ -2697,7 +2697,8 @@ int vkd3d_shader_sm4_parser_create(const struct vkd3d_shader_compile_info *compi
}
++instructions->count;
}
if (sm4->p.shader_version.type == VKD3D_SHADER_TYPE_HULL && !sm4->has_control_point_phase && !sm4->p.failed)
if (sm4->p.program.shader_version.type == VKD3D_SHADER_TYPE_HULL
&& !sm4->has_control_point_phase && !sm4->p.failed)
shader_sm4_validate_default_phase_index_ranges(sm4);
if (!sm4->p.failed)

View File

@ -539,10 +539,9 @@ bool vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser,
parser->location.source_name = source_name;
parser->location.line = 1;
parser->location.column = 0;
parser->shader_version = *version;
parser->ops = ops;
parser->config_flags = vkd3d_shader_init_config_flags();
return vsir_program_init(&parser->program, instruction_reserve);
return vsir_program_init(&parser->program, version, instruction_reserve);
}
void VKD3D_PRINTF_FUNC(3, 4) vkd3d_shader_parser_error(struct vkd3d_shader_parser *parser,
@ -1402,11 +1401,11 @@ static int scan_with_parser(const struct vkd3d_shader_compile_info *compile_info
descriptor_info1 = &local_descriptor_info1;
}
vkd3d_shader_scan_context_init(&context, &parser->shader_version, compile_info,
vkd3d_shader_scan_context_init(&context, &parser->program.shader_version, compile_info,
descriptor_info1, combined_sampler_info, message_context);
if (TRACE_ON())
vkd3d_shader_trace(&parser->program.instructions, &parser->shader_version);
vkd3d_shader_trace(&parser->program);
for (i = 0; i < parser->program.instructions.count; ++i)
{
@ -1583,14 +1582,13 @@ static int vkd3d_shader_parser_compile(struct vkd3d_shader_parser *parser,
switch (compile_info->target_type)
{
case VKD3D_SHADER_TARGET_D3D_ASM:
ret = vkd3d_dxbc_binary_to_text(&parser->program.instructions,
&parser->shader_version, compile_info, out, VSIR_ASM_D3D);
ret = vkd3d_dxbc_binary_to_text(&parser->program, compile_info, out, VSIR_ASM_D3D);
break;
case VKD3D_SHADER_TARGET_GLSL:
if ((ret = scan_with_parser(&scan_info, message_context, &scan_descriptor_info, parser)) < 0)
return ret;
if (!(glsl_generator = vkd3d_glsl_generator_create(&parser->shader_version,
if (!(glsl_generator = vkd3d_glsl_generator_create(&parser->program.shader_version,
message_context, &parser->location)))
{
ERR("Failed to create GLSL generator.\n");

View File

@ -1272,10 +1272,11 @@ enum vkd3d_shader_config_flags
struct vsir_program
{
struct vkd3d_shader_version shader_version;
struct vkd3d_shader_instruction_array instructions;
};
bool vsir_program_init(struct vsir_program *program, unsigned int reserve);
bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_version *version, unsigned int reserve);
void vsir_program_cleanup(struct vsir_program *program);
struct vkd3d_shader_parser
@ -1285,7 +1286,6 @@ struct vkd3d_shader_parser
bool failed;
struct vkd3d_shader_desc shader_desc;
struct vkd3d_shader_version shader_version;
const struct vkd3d_shader_parser_ops *ops;
struct vsir_program program;
@ -1344,8 +1344,7 @@ struct vkd3d_shader_scan_descriptor_info1
unsigned int descriptor_count;
};
void vkd3d_shader_trace(const struct vkd3d_shader_instruction_array *instructions,
const struct vkd3d_shader_version *shader_version);
void vkd3d_shader_trace(const struct vsir_program *program);
const char *shader_get_type_prefix(enum vkd3d_shader_type type);
@ -1367,8 +1366,8 @@ enum vsir_asm_dialect
VSIR_ASM_D3D,
};
enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vkd3d_shader_instruction_array *instructions,
const struct vkd3d_shader_version *shader_version, const struct vkd3d_shader_compile_info *compile_info,
enum vkd3d_result vkd3d_dxbc_binary_to_text(const struct vsir_program *program,
const struct vkd3d_shader_compile_info *compile_info,
struct vkd3d_shader_code *out, enum vsir_asm_dialect dialect);
void vkd3d_string_buffer_cleanup(struct vkd3d_string_buffer *buffer);
struct vkd3d_string_buffer *vkd3d_string_buffer_get(struct vkd3d_string_buffer_cache *list);