vkd3d-shader/dxil: Load hull shader properties.

This commit is contained in:
Conor McCarthy 2023-12-06 16:49:17 +10:00 committed by Alexandre Julliard
parent 02cbc511bb
commit 54016b3ced
Notes: Alexandre Julliard 2024-04-16 23:25:27 +02:00
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Henri Verbeet (@hverbeet)
Approved-by: Alexandre Julliard (@julliard)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/767
3 changed files with 182 additions and 11 deletions

View File

@ -791,6 +791,7 @@ struct sm6_parser
size_t global_symbol_count;
const char *entry_point;
const char *patch_constant_function;
struct vkd3d_shader_dst_param *output_params;
struct vkd3d_shader_dst_param *input_params;
@ -2790,7 +2791,7 @@ static inline uint64_t decode_rotated_signed_value(uint64_t value)
return value << 63;
}
static inline float bitcast_uint64_to_float(uint64_t value)
static float bitcast_uint_to_float(unsigned int value)
{
union
{
@ -2814,6 +2815,23 @@ static inline double bitcast_uint64_to_double(uint64_t value)
return u.double_value;
}
static float register_get_float_value(const struct vkd3d_shader_register *reg)
{
if (!register_is_constant(reg) || !data_type_is_floating_point(reg->data_type))
return 0.0;
if (reg->dimension == VSIR_DIMENSION_VEC4)
WARN("Returning vec4.x.\n");
if (reg->type == VKD3DSPR_IMMCONST64)
{
WARN("Truncating double to float.\n");
return bitcast_uint64_to_double(reg->u.immconst_u64[0]);
}
return bitcast_uint_to_float(reg->u.immconst_u32[0]);
}
static enum vkd3d_result value_allocate_constant_array(struct sm6_value *dst, const struct sm6_type *type,
const uint64_t *operands, struct sm6_parser *sm6)
{
@ -3098,7 +3116,7 @@ static enum vkd3d_result sm6_parser_constants_init(struct sm6_parser *sm6, const
if (type->u.width == 16)
dst->u.reg.u.immconst_u32[0] = record->operands[0];
else if (type->u.width == 32)
dst->u.reg.u.immconst_f32[0] = bitcast_uint64_to_float(record->operands[0]);
dst->u.reg.u.immconst_f32[0] = bitcast_uint_to_float(record->operands[0]);
else if (type->u.width == 64)
dst->u.reg.u.immconst_f64[0] = bitcast_uint64_to_double(record->operands[0]);
else
@ -6728,6 +6746,25 @@ static bool sm6_metadata_get_uint64_value(const struct sm6_parser *sm6,
return true;
}
static bool sm6_metadata_get_float_value(const struct sm6_parser *sm6,
const struct sm6_metadata_value *m, float *f)
{
const struct sm6_value *value;
if (!m || m->type != VKD3D_METADATA_VALUE)
return false;
value = m->u.value;
if (!sm6_value_is_constant(value))
return false;
if (!sm6_type_is_floating_point(value->type))
return false;
*f = register_get_float_value(&value->u.reg);
return true;
}
static void sm6_parser_metadata_attachment_block_init(struct sm6_parser *sm6, const struct dxil_block *target_block,
const struct dxil_block *block)
{
@ -8762,6 +8799,14 @@ static enum vkd3d_result sm6_parser_emit_thread_group(struct sm6_parser *sm6, co
return VKD3D_OK;
}
static void sm6_parser_emit_dcl_count(struct sm6_parser *sm6, enum vkd3d_shader_opcode handler_idx, unsigned int count)
{
struct vkd3d_shader_instruction *ins;
ins = sm6_parser_add_instruction(sm6, handler_idx);
ins->declaration.count = count;
}
static void sm6_parser_emit_dcl_tessellator_domain(struct sm6_parser *sm6,
enum vkd3d_tessellator_domain tessellator_domain)
{
@ -8778,16 +8823,74 @@ static void sm6_parser_emit_dcl_tessellator_domain(struct sm6_parser *sm6,
ins->declaration.tessellator_domain = tessellator_domain;
}
static void sm6_parser_validate_control_point_count(struct sm6_parser *sm6, unsigned int count)
static void sm6_parser_validate_control_point_count(struct sm6_parser *sm6, unsigned int count,
const char *type)
{
if (!count || count > 32)
{
WARN("Invalid control point count %u.\n", count);
WARN("%s control point count %u invalid.\n", type, count);
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES,
"Domain shader input control point count %u is invalid.", count);
"%s control point count %u is invalid.", type, count);
}
}
static void sm6_parser_emit_dcl_tessellator_partitioning(struct sm6_parser *sm6,
enum vkd3d_shader_tessellator_partitioning tessellator_partitioning)
{
struct vkd3d_shader_instruction *ins;
if (!tessellator_partitioning || tessellator_partitioning > VKD3D_SHADER_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN)
{
WARN("Unhandled partitioning %u.\n", tessellator_partitioning);
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES,
"Hull shader tessellator partitioning %u is unhandled.", tessellator_partitioning);
}
ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_TESSELLATOR_PARTITIONING);
ins->declaration.tessellator_partitioning = tessellator_partitioning;
}
static void sm6_parser_emit_dcl_tessellator_output_primitive(struct sm6_parser *sm6,
enum vkd3d_shader_tessellator_output_primitive primitive)
{
struct vkd3d_shader_instruction *ins;
if (!primitive || primitive > VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CCW)
{
WARN("Unhandled output primitive %u.\n", primitive);
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES,
"Hull shader tessellator output primitive %u is unhandled.", primitive);
}
ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE);
ins->declaration.tessellator_output_primitive = primitive;
}
static void sm6_parser_emit_dcl_max_tessellation_factor(struct sm6_parser *sm6, struct sm6_metadata_value *m)
{
struct vkd3d_shader_instruction *ins;
float max_tessellation_factor;
if (!sm6_metadata_get_float_value(sm6, m, &max_tessellation_factor))
{
WARN("Max tess factor property is not a float value.\n");
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES,
"Hull shader max tessellation factor property operand is not a float.");
return;
}
/* Exclude non-finite values. */
if (!(max_tessellation_factor >= 1.0f && max_tessellation_factor <= 64.0f))
{
WARN("Invalid max tess factor %f.\n", max_tessellation_factor);
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES,
"Hull shader max tessellation factor %f is invalid.", max_tessellation_factor);
}
ins = sm6_parser_add_instruction(sm6, VKD3DSIH_DCL_HS_MAX_TESSFACTOR);
ins->declaration.max_tessellation_factor = max_tessellation_factor;
}
static enum vkd3d_tessellator_domain sm6_parser_ds_properties_init(struct sm6_parser *sm6,
const struct sm6_metadata_value *m)
{
@ -8830,12 +8933,77 @@ static enum vkd3d_tessellator_domain sm6_parser_ds_properties_init(struct sm6_pa
}
sm6_parser_emit_dcl_tessellator_domain(sm6, operands[0]);
sm6_parser_validate_control_point_count(sm6, operands[1]);
sm6_parser_validate_control_point_count(sm6, operands[1], "Domain shader input");
sm6->p.program.input_control_point_count = operands[1];
return operands[0];
}
static enum vkd3d_tessellator_domain sm6_parser_hs_properties_init(struct sm6_parser *sm6,
const struct sm6_metadata_value *m)
{
const struct sm6_metadata_node *node;
unsigned int operands[6] = {0};
unsigned int i;
if (!m || !sm6_metadata_value_is_node(m))
{
WARN("Missing or invalid HS properties.\n");
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES,
"Hull shader properties node is missing or invalid.");
return 0;
}
node = m->u.node;
if (node->operand_count < 7)
{
WARN("Invalid operand count %u.\n", node->operand_count);
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND_COUNT,
"Hull shader properties operand count %u is invalid.", node->operand_count);
return 0;
}
if (node->operand_count > 7)
{
WARN("Ignoring %u extra operands.\n", node->operand_count - 7);
vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_IGNORING_OPERANDS,
"Ignoring %u extra operands for hull shader properties.", node->operand_count - 7);
}
m = node->operands[0];
if (!sm6_metadata_value_is_value(m) || !sm6_value_is_function_dcl(m->u.value))
{
WARN("Patch constant function node is not a function value.\n");
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES,
"Hull shader patch constant function node is not a function value.");
}
else
{
sm6->patch_constant_function = m->u.value->u.function.name;
}
for (i = 1; i < min(node->operand_count, ARRAY_SIZE(operands)); ++i)
{
if (!sm6_metadata_get_uint_value(sm6, node->operands[i], &operands[i]))
{
WARN("HS property at index %u is not a uint value.\n", i);
vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_PROPERTIES,
"Hull shader properties operand at index %u is not an integer.", i);
}
}
sm6_parser_validate_control_point_count(sm6, operands[1], "Hull shader input");
sm6->p.program.input_control_point_count = operands[1];
sm6_parser_validate_control_point_count(sm6, operands[2], "Hull shader output");
sm6_parser_emit_dcl_count(sm6, VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT, operands[2]);
sm6->p.program.output_control_point_count = operands[2];
sm6_parser_emit_dcl_tessellator_domain(sm6, operands[3]);
sm6_parser_emit_dcl_tessellator_partitioning(sm6, operands[4]);
sm6_parser_emit_dcl_tessellator_output_primitive(sm6, operands[5]);
sm6_parser_emit_dcl_max_tessellation_factor(sm6, node->operands[6]);
return operands[3];
}
static enum vkd3d_result sm6_parser_entry_point_init(struct sm6_parser *sm6)
{
const struct sm6_metadata_value *m = sm6_parser_find_named_metadata(sm6, "dx.entryPoints");
@ -8916,6 +9084,9 @@ static enum vkd3d_result sm6_parser_entry_point_init(struct sm6_parser *sm6)
case SHADER_PROPERTIES_DOMAIN:
tessellator_domain = sm6_parser_ds_properties_init(sm6, node->operands[i + 1]);
break;
case SHADER_PROPERTIES_HULL:
tessellator_domain = sm6_parser_hs_properties_init(sm6, node->operands[i + 1]);
break;
case SHADER_PROPERTIES_COMPUTE:
if ((ret = sm6_parser_emit_thread_group(sm6, node->operands[i + 1])) < 0)
return ret;

View File

@ -223,11 +223,6 @@ enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d
}
}
static bool data_type_is_floating_point(enum vkd3d_data_type data_type)
{
return data_type == VKD3D_DATA_HALF || data_type == VKD3D_DATA_FLOAT || data_type == VKD3D_DATA_DOUBLE;
}
#define VKD3D_SPIRV_VERSION 0x00010000
#define VKD3D_SPIRV_GENERATOR_ID 18
#define VKD3D_SPIRV_GENERATOR_VERSION 11

View File

@ -641,6 +641,11 @@ static inline bool data_type_is_bool(enum vkd3d_data_type data_type)
return data_type == VKD3D_DATA_BOOL;
}
static inline bool data_type_is_floating_point(enum vkd3d_data_type data_type)
{
return data_type == VKD3D_DATA_HALF || data_type == VKD3D_DATA_FLOAT || data_type == VKD3D_DATA_DOUBLE;
}
static inline bool data_type_is_64_bit(enum vkd3d_data_type data_type)
{
return data_type == VKD3D_DATA_DOUBLE || data_type == VKD3D_DATA_UINT64;