vkd3d-shader/fx: Implement parsing states objects.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
This commit is contained in:
Nikolay Sivov 2024-11-12 14:31:37 +01:00 committed by Henri Verbeet
parent 3d53d90d4b
commit 21681489ed
Notes: Henri Verbeet 2024-11-13 16:30:09 +01:00
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1256

View File

@ -500,6 +500,9 @@ enum fx_4_type_constants
/* Object types */
FX_4_OBJECT_TYPE_STRING = 0x1,
FX_4_OBJECT_TYPE_BLEND_STATE = 0x2,
FX_4_OBJECT_TYPE_DEPTH_STENCIL_STATE = 0x3,
FX_4_OBJECT_TYPE_RASTERIZER_STATE = 0x4,
FX_4_OBJECT_TYPE_PIXEL_SHADER = 0x5,
FX_4_OBJECT_TYPE_VERTEX_SHADER = 0x6,
FX_4_OBJECT_TYPE_GEOMETRY_SHADER = 0x7,
@ -516,6 +519,7 @@ enum fx_4_type_constants
FX_4_OBJECT_TYPE_TEXTURE_CUBE = 0x11,
FX_4_OBJECT_TYPE_RTV = 0x13,
FX_4_OBJECT_TYPE_DSV = 0x14,
FX_4_OBJECT_TYPE_SAMPLER_STATE = 0x15,
FX_4_OBJECT_TYPE_TEXTURE_CUBEARRAY = 0x17,
FX_5_OBJECT_TYPE_GEOMETRY_SHADER = 0x1b,
@ -540,6 +544,12 @@ enum fx_4_type_constants
FX_4_TYPE_CLASS_NUMERIC = 1,
FX_4_TYPE_CLASS_OBJECT = 2,
FX_4_TYPE_CLASS_STRUCT = 3,
/* Assignment types */
FX_4_ASSIGNMENT_CONSTANT = 0x1,
FX_4_ASSIGNMENT_VARIABLE = 0x2,
FX_4_ASSIGNMENT_ARRAY_CONSTANT_INDEX = 0x3,
FX_4_ASSIGNMENT_ARRAY_VARIABLE_INDEX = 0x4,
};
static const uint32_t fx_4_numeric_base_types[] =
@ -816,7 +826,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co
}
else if (element_type->class == HLSL_CLASS_SAMPLER)
{
put_u32_unaligned(buffer, 21);
put_u32_unaligned(buffer, FX_4_OBJECT_TYPE_SAMPLER_STATE);
}
else if (element_type->class == HLSL_CLASS_UAV)
{
@ -852,15 +862,15 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co
}
else if (element_type->class == HLSL_CLASS_RASTERIZER_STATE)
{
put_u32_unaligned(buffer, 4);
put_u32_unaligned(buffer, FX_4_OBJECT_TYPE_RASTERIZER_STATE);
}
else if (element_type->class == HLSL_CLASS_DEPTH_STENCIL_STATE)
{
put_u32_unaligned(buffer, 3);
put_u32_unaligned(buffer, FX_4_OBJECT_TYPE_DEPTH_STENCIL_STATE);
}
else if (element_type->class == HLSL_CLASS_BLEND_STATE)
{
put_u32_unaligned(buffer, 2);
put_u32_unaligned(buffer, FX_4_OBJECT_TYPE_BLEND_STATE);
}
else if (element_type->class == HLSL_CLASS_STRING)
{
@ -1649,7 +1659,7 @@ static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hl
c = hlsl_ir_constant(value);
value_offset = write_fx_4_state_numeric_value(c, fx);
assignment_type = 1;
assignment_type = FX_4_ASSIGNMENT_CONSTANT;
break;
}
case HLSL_IR_LOAD:
@ -1660,7 +1670,7 @@ static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hl
hlsl_fixme(ctx, &var->loc, "Indexed access in RHS values is not implemented.");
value_offset = write_fx_4_string(load->src.var->name, fx);
assignment_type = 2;
assignment_type = FX_4_ASSIGNMENT_VARIABLE;
break;
}
case HLSL_IR_INDEX:
@ -1687,7 +1697,7 @@ static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hl
c = hlsl_ir_constant(idx);
value_offset = put_u32(unstructured, value_offset);
put_u32(unstructured, c->value.u[0].u);
assignment_type = 3;
assignment_type = FX_4_ASSIGNMENT_ARRAY_CONSTANT_INDEX;
if (c->value.u[0].u >= type->e.array.elements_count)
hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_OFFSET_OUT_OF_BOUNDS,
@ -1708,7 +1718,7 @@ static void write_fx_4_state_assignment(const struct hlsl_ir_var *var, struct hl
value_offset = put_u32(unstructured, value_offset);
put_u32(unstructured, offset);
assignment_type = 4;
assignment_type = FX_4_ASSIGNMENT_ARRAY_VARIABLE_INDEX;
break;
}
}
@ -1824,6 +1834,7 @@ enum state_property_component_type
FX_BLEND,
FX_VERTEXSHADER,
FX_PIXELSHADER,
FX_COMPONENT_TYPE_COUNT,
};
static inline bool is_object_fx_type(enum state_property_component_type type)
@ -1894,9 +1905,6 @@ static inline enum hlsl_base_type hlsl_type_from_fx_type(enum state_property_com
}
}
static void resolve_fx_4_state_block_values(struct hlsl_ir_var *var, struct hlsl_state_block_entry *entry,
struct fx_write_context *fx)
{
static const struct rhs_named_value filter_values[] =
{
{ "MIN_MAG_MIP_POINT", 0x00 },
@ -2036,7 +2044,7 @@ static void resolve_fx_4_state_block_values(struct hlsl_ir_var *var, struct hlsl
{ NULL }
};
static const struct state
static const struct fx_4_state
{
const char *name;
enum hlsl_type_class container;
@ -2044,10 +2052,10 @@ static void resolve_fx_4_state_block_values(struct hlsl_ir_var *var, struct hlsl
enum state_property_component_type type;
unsigned int dimx;
unsigned int array_size;
uint32_t id;
int id;
const struct rhs_named_value *values;
}
states[] =
fx_4_states[] =
{
{ "RasterizerState", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_RASTERIZER, 1, 1, 0 },
{ "DepthStencilState", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_DEPTHSTENCIL, 1, 1, 1 },
@ -2087,6 +2095,16 @@ static void resolve_fx_4_state_block_values(struct hlsl_ir_var *var, struct hlsl
{ "BackFaceStencilPass", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 34, stencil_op_values },
{ "BackFaceStencilFunc", HLSL_CLASS_DEPTH_STENCIL_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 35, comparison_values },
{ "AlphaToCoverageEnable", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 1, 36, bool_values },
{ "BlendEnable", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 8, 37, bool_values },
{ "SrcBlend", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 38, blend_values },
{ "DestBlend", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 39, blend_values },
{ "BlendOp", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 40, blendop_values },
{ "SrcBlendAlpha", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 41, blend_values },
{ "DestBlendAlpha", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 42, blend_values },
{ "BlendOpAlpha", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 43, blendop_values },
{ "RenderTargetWriteMask", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_UINT8, 1, 8, 44 },
{ "Filter", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 45, filter_values },
{ "AddressU", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 46, address_values },
{ "AddressV", HLSL_CLASS_SAMPLER, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 47, address_values },
@ -2104,20 +2122,10 @@ static void resolve_fx_4_state_block_values(struct hlsl_ir_var *var, struct hlsl
{ "ComputeShader", HLSL_CLASS_PASS, HLSL_CLASS_SCALAR, FX_COMPUTESHADER, 1, 1, 58 },
};
static const struct state fx_4_blend_states[] =
static void resolve_fx_4_state_block_values(struct hlsl_ir_var *var, struct hlsl_state_block_entry *entry,
struct fx_write_context *fx)
{
{ "AlphaToCoverageEnable", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 1, 36, bool_values },
{ "BlendEnable", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 8, 37, bool_values },
{ "SrcBlend", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 38, blend_values },
{ "DestBlend", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 39, blend_values },
{ "BlendOp", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 40, blendop_values },
{ "SrcBlendAlpha", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 41, blend_values },
{ "DestBlendAlpha", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 42, blend_values },
{ "BlendOpAlpha", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 43, blendop_values },
{ "RenderTargetWriteMask", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_UINT8, 1, 8, 44 },
};
static const struct state fx_5_blend_states[] =
static const struct fx_4_state fx_5_blend_states[] =
{
{ "AlphaToCoverageEnable", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 1, 36, bool_values },
{ "BlendEnable", HLSL_CLASS_BLEND_STATE, HLSL_CLASS_SCALAR, FX_BOOL, 1, 8, 37, bool_values },
@ -2132,36 +2140,28 @@ static void resolve_fx_4_state_block_values(struct hlsl_ir_var *var, struct hlsl
struct state_table
{
const struct state *ptr;
const struct fx_4_state *ptr;
unsigned int count;
} table;
const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type);
struct replace_state_context replace_context;
const struct fx_4_state *state = NULL;
struct hlsl_type *state_type = NULL;
struct hlsl_ir_node *node, *cast;
const struct state *state = NULL;
struct hlsl_ctx *ctx = fx->ctx;
enum hlsl_base_type base_type;
unsigned int i;
if (type->class == HLSL_CLASS_BLEND_STATE)
{
if (ctx->profile->major_version == 4)
{
table.ptr = fx_4_blend_states;
table.count = ARRAY_SIZE(fx_4_blend_states);
}
else
if (type->class == HLSL_CLASS_BLEND_STATE && ctx->profile->major_version == 5)
{
table.ptr = fx_5_blend_states;
table.count = ARRAY_SIZE(fx_5_blend_states);
}
}
else
{
table.ptr = states;
table.count = ARRAY_SIZE(states);
table.ptr = fx_4_states;
table.count = ARRAY_SIZE(fx_4_states);
}
for (i = 0; i < table.count; ++i)
@ -3071,6 +3071,9 @@ static void fx_parse_fx_4_annotations(struct fx_parser *parser)
const char *name, *type_name;
uint32_t count, i, value;
if (parser->failed)
return;
count = fx_parser_read_u32(parser);
if (!count)
@ -3329,6 +3332,10 @@ static bool fx_4_object_has_initializer(const struct fx_4_binary_type *type)
switch (type->typeinfo)
{
case FX_4_OBJECT_TYPE_STRING:
case FX_4_OBJECT_TYPE_BLEND_STATE:
case FX_4_OBJECT_TYPE_DEPTH_STENCIL_STATE:
case FX_4_OBJECT_TYPE_RASTERIZER_STATE:
case FX_4_OBJECT_TYPE_SAMPLER_STATE:
case FX_4_OBJECT_TYPE_PIXEL_SHADER:
case FX_4_OBJECT_TYPE_VERTEX_SHADER:
case FX_4_OBJECT_TYPE_GEOMETRY_SHADER:
@ -3343,9 +3350,160 @@ static bool fx_4_object_has_initializer(const struct fx_4_binary_type *type)
}
}
static int fx_4_state_id_compare(const void *a, const void *b)
{
const struct fx_4_state *state = b;
int id = *(int *)a;
return id - state->id;
}
static void fx_4_parse_state_object_initializer(struct fx_parser *parser, uint32_t count,
enum hlsl_type_class type_class)
{
struct fx_4_assignment
{
uint32_t id;
uint32_t lhs_index;
uint32_t type;
uint32_t value;
} entry;
struct
{
uint32_t name;
uint32_t index;
} index;
struct
{
uint32_t type;
union
{
uint32_t u;
float f;
};
} value;
static const char *value_types[FX_COMPONENT_TYPE_COUNT] =
{
[FX_BOOL] = "bool",
[FX_FLOAT] = "float",
[FX_UINT] = "uint",
[FX_UINT8] = "byte",
};
const struct rhs_named_value *named_value;
uint32_t i, j, comp_count;
struct fx_4_state *state;
for (i = 0; i < count; ++i)
{
fx_parser_read_u32s(parser, &entry, sizeof(entry));
if (!(state = bsearch(&entry.id, fx_4_states, ARRAY_SIZE(fx_4_states),
sizeof(*fx_4_states), fx_4_state_id_compare)))
{
fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, "Unrecognized state id %#x.\n", entry.id);
break;
}
if (state->container != type_class)
{
fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA,
"State '%s' does not belong to object type class %#x.", state->name, type_class);
break;
}
parse_fx_print_indent(parser);
vkd3d_string_buffer_printf(&parser->buffer, "%s", state->name);
if (state->array_size > 1)
vkd3d_string_buffer_printf(&parser->buffer, "[%u]", entry.lhs_index);
vkd3d_string_buffer_printf(&parser->buffer, " = ");
switch (entry.type)
{
case FX_4_ASSIGNMENT_CONSTANT:
if (value_types[state->type])
vkd3d_string_buffer_printf(&parser->buffer, "%s", value_types[state->type]);
if (state->dimx > 1)
vkd3d_string_buffer_printf(&parser->buffer, "%u", state->dimx);
vkd3d_string_buffer_printf(&parser->buffer, "(");
fx_parser_read_unstructured(parser, &comp_count, entry.value, sizeof(uint32_t));
named_value = NULL;
if (comp_count == 1 && state->values && (state->type == FX_UINT || state->type == FX_BOOL))
{
const struct rhs_named_value *ptr = state->values;
fx_parser_read_unstructured(parser, &value, entry.value + 4, sizeof(value));
while (ptr->name)
{
if (value.u == ptr->value)
{
named_value = ptr;
break;
}
++ptr;
}
}
if (named_value)
{
vkd3d_string_buffer_printf(&parser->buffer, "%s /* %u */", named_value->name, named_value->value);
}
else
{
uint32_t offset = entry.value + 4;
for (j = 0; j < comp_count; ++j, offset += sizeof(value))
{
fx_parser_read_unstructured(parser, &value, offset, sizeof(value));
if (state->type == FX_UINT8)
vkd3d_string_buffer_printf(&parser->buffer, "0x%.2x", value.u);
else if (state->type == FX_UINT)
vkd3d_string_buffer_printf(&parser->buffer, "%u", value.u);
else if (state->type == FX_FLOAT)
vkd3d_string_buffer_printf(&parser->buffer, "%g", value.f);
if (comp_count > 1 && j < comp_count - 1)
vkd3d_string_buffer_printf(&parser->buffer, ", ");
}
}
vkd3d_string_buffer_printf(&parser->buffer, ")");
break;
case FX_4_ASSIGNMENT_VARIABLE:
vkd3d_string_buffer_printf(&parser->buffer, "%s", fx_4_get_string(parser, entry.value));
break;
case FX_4_ASSIGNMENT_ARRAY_CONSTANT_INDEX:
fx_parser_read_unstructured(parser, &index, entry.value, sizeof(index));
vkd3d_string_buffer_printf(&parser->buffer, "%s[%u]", fx_4_get_string(parser, index.name), index.index);
break;
case FX_4_ASSIGNMENT_ARRAY_VARIABLE_INDEX:
fx_parser_read_unstructured(parser, &index, entry.value, sizeof(index));
vkd3d_string_buffer_printf(&parser->buffer, "%s[%s]", fx_4_get_string(parser, index.name),
fx_4_get_string(parser, index.index));
break;
default:
fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED,
"Unsupported assignment type %u.\n", entry.type);
}
vkd3d_string_buffer_printf(&parser->buffer, ";\n");
}
}
static void fx_4_parse_object_initializer(struct fx_parser *parser, const struct fx_4_binary_type *type)
{
unsigned int i, element_count;
static const enum hlsl_type_class type_classes[] =
{
[FX_4_OBJECT_TYPE_BLEND_STATE] = HLSL_CLASS_BLEND_STATE,
[FX_4_OBJECT_TYPE_DEPTH_STENCIL_STATE] = HLSL_CLASS_DEPTH_STENCIL_STATE,
[FX_4_OBJECT_TYPE_RASTERIZER_STATE] = HLSL_CLASS_RASTERIZER_STATE,
[FX_4_OBJECT_TYPE_SAMPLER_STATE] = HLSL_CLASS_SAMPLER,
};
unsigned int i, element_count, count;
uint32_t value;
if (!fx_4_object_has_initializer(type))
@ -3362,6 +3520,16 @@ static void fx_4_parse_object_initializer(struct fx_parser *parser, const struct
value = fx_parser_read_u32(parser);
fx_4_parse_string_initializer(parser, value);
break;
case FX_4_OBJECT_TYPE_BLEND_STATE:
case FX_4_OBJECT_TYPE_DEPTH_STENCIL_STATE:
case FX_4_OBJECT_TYPE_RASTERIZER_STATE:
case FX_4_OBJECT_TYPE_SAMPLER_STATE:
count = fx_parser_read_u32(parser);
parse_fx_start_indent(parser);
fx_4_parse_state_object_initializer(parser, count, type_classes[type->typeinfo]);
parse_fx_end_indent(parser);
break;
case FX_4_OBJECT_TYPE_PIXEL_SHADER:
case FX_4_OBJECT_TYPE_VERTEX_SHADER:
case FX_4_OBJECT_TYPE_GEOMETRY_SHADER:
@ -3402,6 +3570,9 @@ static void fx_4_parse_objects(struct fx_parser *parser)
for (i = 0; i < parser->object_count; ++i)
{
if (parser->failed)
return;
fx_parser_read_u32s(parser, &var, sizeof(var));
fx_parser_read_unstructured(parser, &type, var.type, sizeof(type));
@ -3462,9 +3633,9 @@ static void fx_parse_fx_4_technique(struct fx_parser *parser)
parse_fx_print_indent(parser);
vkd3d_string_buffer_printf(&parser->buffer, "{\n");
if (pass.count)
fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED,
"Parsing pass states is not implemented.\n");
parse_fx_start_indent(parser);
fx_4_parse_state_object_initializer(parser, pass.count, HLSL_CLASS_PASS);
parse_fx_end_indent(parser);
parse_fx_print_indent(parser);
vkd3d_string_buffer_printf(&parser->buffer, "}\n\n");