From ea3477f55df517065cc716c27e2df7ea68f6760e Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Tue, 23 Apr 2024 08:01:19 +1000 Subject: [PATCH] Updated vkd3d to 7b4a1fdfbc192cfd02ffb6cf18c0a86b2f6eaeb4. --- libs/vkd3d/include/private/vkd3d_common.h | 70 ++++++ libs/vkd3d/include/vkd3d.h | 115 +++++++++- libs/vkd3d/libs/vkd3d-shader/dxil.c | 205 ++++++++++++++++-- libs/vkd3d/libs/vkd3d-shader/glsl.c | 1 + libs/vkd3d/libs/vkd3d-shader/hlsl.h | 2 +- libs/vkd3d/libs/vkd3d-shader/hlsl.y | 72 ++++-- libs/vkd3d/libs/vkd3d-shader/ir.c | 14 +- .../libs/vkd3d-shader/vkd3d_shader_private.h | 5 + libs/vkd3d/libs/vkd3d/vkd3d_private.h | 84 ------- 9 files changed, 430 insertions(+), 138 deletions(-) diff --git a/libs/vkd3d/include/private/vkd3d_common.h b/libs/vkd3d/include/private/vkd3d_common.h index f9df47d339c..1da73bcfb2e 100644 --- a/libs/vkd3d/include/private/vkd3d_common.h +++ b/libs/vkd3d/include/private/vkd3d_common.h @@ -492,6 +492,76 @@ static inline void vkd3d_mutex_destroy(struct vkd3d_mutex *lock) #endif } +struct vkd3d_cond +{ +#ifdef _WIN32 + CONDITION_VARIABLE cond; +#else + pthread_cond_t cond; +#endif +}; + +static inline void vkd3d_cond_init(struct vkd3d_cond *cond) +{ +#ifdef _WIN32 + InitializeConditionVariable(&cond->cond); +#else + int ret; + + if ((ret = pthread_cond_init(&cond->cond, NULL))) + ERR("Failed to initialise the condition variable, ret %d.\n", ret); +#endif +} + +static inline void vkd3d_cond_signal(struct vkd3d_cond *cond) +{ +#ifdef _WIN32 + WakeConditionVariable(&cond->cond); +#else + int ret; + + if ((ret = pthread_cond_signal(&cond->cond))) + ERR("Failed to signal the condition variable, ret %d.\n", ret); +#endif +} + +static inline void vkd3d_cond_broadcast(struct vkd3d_cond *cond) +{ +#ifdef _WIN32 + WakeAllConditionVariable(&cond->cond); +#else + int ret; + + if ((ret = pthread_cond_broadcast(&cond->cond))) + ERR("Failed to broadcast the condition variable, ret %d.\n", ret); +#endif +} + +static inline void vkd3d_cond_wait(struct vkd3d_cond *cond, struct vkd3d_mutex *lock) +{ +#ifdef _WIN32 + if (!SleepConditionVariableCS(&cond->cond, &lock->lock, INFINITE)) + ERR("Failed to wait on the condition variable, error %lu.\n", GetLastError()); +#else + int ret; + + if ((ret = pthread_cond_wait(&cond->cond, &lock->lock))) + ERR("Failed to wait on the condition variable, ret %d.\n", ret); +#endif +} + +static inline void vkd3d_cond_destroy(struct vkd3d_cond *cond) +{ +#ifdef _WIN32 + /* Nothing to do. */ +#else + int ret; + + if ((ret = pthread_cond_destroy(&cond->cond))) + ERR("Failed to destroy the condition variable, ret %d.\n", ret); +#endif +} + static inline void vkd3d_parse_version(const char *version, int *major, int *minor) { *major = atoi(version); diff --git a/libs/vkd3d/include/vkd3d.h b/libs/vkd3d/include/vkd3d.h index aa68b70e1bf..71c56331d86 100644 --- a/libs/vkd3d/include/vkd3d.h +++ b/libs/vkd3d/include/vkd3d.h @@ -46,21 +46,37 @@ extern "C" { * \since 1.0 */ +/** The type of a chained structure. */ enum vkd3d_structure_type { - /* 1.0 */ + /** The structure is a vkd3d_instance_create_info structure. */ VKD3D_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + /** The structure is a vkd3d_device_create_info structure. */ VKD3D_STRUCTURE_TYPE_DEVICE_CREATE_INFO, + /** The structure is a vkd3d_image_resource_create_info structure. */ VKD3D_STRUCTURE_TYPE_IMAGE_RESOURCE_CREATE_INFO, - /* 1.1 */ + /** + * The structure is a vkd3d_optional_instance_extensions_info structure. + * \since 1.1 + */ VKD3D_STRUCTURE_TYPE_OPTIONAL_INSTANCE_EXTENSIONS_INFO, - /* 1.2 */ + /** + * The structure is a vkd3d_optional_device_extensions_info structure. + * \since 1.2 + */ VKD3D_STRUCTURE_TYPE_OPTIONAL_DEVICE_EXTENSIONS_INFO, + /** + * The structure is a vkd3d_application_info structure. + * \since 1.2 + */ VKD3D_STRUCTURE_TYPE_APPLICATION_INFO, - /* 1.3 */ + /** + * The structure is a vkd3d_host_time_domain_info structure. + * \since 1.3 + */ VKD3D_STRUCTURE_TYPE_HOST_TIME_DOMAIN_INFO, VKD3D_FORCE_32_BIT_ENUM(VKD3D_STRUCTURE_TYPE), @@ -93,54 +109,131 @@ typedef HRESULT (*PFN_vkd3d_join_thread)(void *thread); struct vkd3d_instance; +/** + * A chained structure containing instance creation parameters. + */ struct vkd3d_instance_create_info { + /** Must be set to VKD3D_STRUCTURE_TYPE_INSTANCE_CREATE_INFO. */ enum vkd3d_structure_type type; + /** Optional pointer to a structure containing further parameters. */ const void *next; + /** An pointer to a function to signal events. */ PFN_vkd3d_signal_event pfn_signal_event; + /** + * An optional pointer to a function to create threads. If this is NULL vkd3d will use a + * function of its choice, depending on the platform. It must be NULL if and only if + * pfn_join_thread is NULL. + */ PFN_vkd3d_create_thread pfn_create_thread; + /** + * An optional pointer to a function to join threads. If this is NULL vkd3d will use a + * function of its choice, depending on the platform. It must be NULL if and only if + * pfn_create_thread is NULL. + */ PFN_vkd3d_join_thread pfn_join_thread; + /** The size of type WCHAR. It must be 2 or 4 and should normally be set to sizeof(WCHAR). */ size_t wchar_size; - /* If set to NULL, libvkd3d loads libvulkan. */ + /** + * A pointer to the vkGetInstanceProcAddr Vulkan function, which will be used to load all the + * other Vulkan functions. If set to NULL, vkd3d will search and use the Vulkan loader. + */ PFN_vkGetInstanceProcAddr pfn_vkGetInstanceProcAddr; + /** + * A list of Vulkan instance extensions to request. They are intended as required, so instance + * creation will fail if any of them is not available. + */ const char * const *instance_extensions; + /** The number of elements in the instance_extensions array. */ uint32_t instance_extension_count; }; -/* Extends vkd3d_instance_create_info. Available since 1.1. */ +/** + * A chained structure to specify optional instance extensions. + * + * This structure extends vkd3d_instance_create_info. + * + * \since 1.1 + */ struct vkd3d_optional_instance_extensions_info { + /** Must be set to VKD3D_STRUCTURE_TYPE_OPTIONAL_INSTANCE_EXTENSIONS_INFO. */ enum vkd3d_structure_type type; + /** Optional pointer to a structure containing further parameters. */ const void *next; + /** + * A list of optional Vulkan instance extensions to request. Instance creation does not fail if + * they are not available. + */ const char * const *extensions; + /** The number of elements in the extensions array. */ uint32_t extension_count; }; -/* Extends vkd3d_instance_create_info. Available since 1.2. */ +/** + * A chained structure to specify application information. + * + * This structure extends vkd3d_instance_create_info. + * + * \since 1.2 + */ struct vkd3d_application_info { + /** Must be set to VKD3D_STRUCTURE_TYPE_APPLICATION_INFO. */ enum vkd3d_structure_type type; + /** Optional pointer to a structure containing further parameters. */ const void *next; + /** + * The application's name, to be passed to the Vulkan implementation. If it is NULL, a name is + * computed from the process executable filename. If that cannot be done, the empty string is + * used. + */ const char *application_name; + /** The application's version, to be passed to the Vulkan implementation. */ uint32_t application_version; - const char *engine_name; /* "vkd3d" if NULL */ - uint32_t engine_version; /* vkd3d version if engine_name is NULL */ - + /** + * The engine name, to be passed to the Vulkan implementation. If it is NULL, "vkd3d" is used. + */ + const char *engine_name; + /** + * The engine version, to be passed to the Vulkan implementation. If it is 0, the version is + * computed from the vkd3d library version. + */ + uint32_t engine_version; + + /** + * The vkd3d API version to use, to guarantee backward compatibility of the shared library. If + * this chained structure is not used then VKD3D_API_VERSION_1_0 is used. + */ enum vkd3d_api_version api_version; }; -/* Extends vkd3d_instance_create_info. Available since 1.3. */ +/** + * A chained structure to specify the host time domain. + * + * This structure extends vkd3d_instance_create_info. + * + * \since 1.3 + */ struct vkd3d_host_time_domain_info { + /** Must be set to VKD3D_STRUCTURE_TYPE_HOST_TIME_DOMAIN_INFO. */ enum vkd3d_structure_type type; + /** Optional pointer to a structure containing further parameters. */ const void *next; + /** + * The number of clock ticks per second, used for GetClockCalibration(). It should normally + * match the expected result of QueryPerformanceFrequency(). If this chained structure is not + * used then 10 millions is used, which means that each tick is a tenth of microsecond, or + * equivalently 100 nanoseconds. + */ uint64_t ticks_per_second; }; diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c index 220ba773887..d07d5adee70 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c @@ -419,6 +419,11 @@ enum dx_intrinsic_opcode DX_FLATTENED_THREAD_ID_IN_GROUP = 96, DX_MAKE_DOUBLE = 101, DX_SPLIT_DOUBLE = 102, + DX_LOAD_OUTPUT_CONTROL_POINT = 103, + DX_LOAD_PATCH_CONSTANT = 104, + DX_DOMAIN_LOCATION = 105, + DX_STORE_PATCH_CONSTANT = 106, + DX_OUTPUT_CONTROL_POINT_ID = 107, DX_PRIMITIVE_ID = 108, DX_LEGACY_F32TOF16 = 130, DX_LEGACY_F16TOF32 = 131, @@ -799,6 +804,7 @@ struct sm6_parser struct vkd3d_shader_dst_param *output_params; struct vkd3d_shader_dst_param *input_params; + struct vkd3d_shader_dst_param *patch_constant_params; uint32_t io_regs_declared[(VKD3DSPR_COUNT + 0x1f) / 0x20]; struct sm6_function *functions; @@ -2433,10 +2439,12 @@ static void register_index_address_init(struct vkd3d_shader_register_index *idx, if (sm6_value_is_constant(address)) { idx->offset = sm6_value_get_constant_uint(address); + idx->rel_addr = NULL; } else if (sm6_value_is_undef(address)) { idx->offset = 0; + idx->rel_addr = NULL; } else { @@ -2515,7 +2523,7 @@ static size_t sm6_parser_compute_max_value_count(struct sm6_parser *sm6, * overestimate the value count somewhat, but this should be no problem. */ value_count = size_add_with_overflow_check(value_count, max(block->record_count, 1u) - 1); sm6->value_capacity = max(sm6->value_capacity, value_count); - sm6->functions[sm6->function_count].value_count = value_count; + sm6->functions[sm6->function_count++].value_count = value_count; /* The value count returns to its previous value after handling a function. */ if (value_count < SIZE_MAX) value_count = old_value_count; @@ -3689,12 +3697,35 @@ static enum vkd3d_shader_register_type register_type_from_dxil_semantic_kind( } static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shader_signature *s, - enum vkd3d_shader_register_type reg_type, struct vkd3d_shader_dst_param *params) + bool is_input, enum vkd3d_shader_register_type reg_type, struct vkd3d_shader_dst_param *params) { + enum vkd3d_shader_type shader_type = sm6->p.program.shader_version.type; + bool is_patch_constant, is_control_point; struct vkd3d_shader_dst_param *param; const struct signature_element *e; unsigned int i, count; + is_patch_constant = reg_type == VKD3DSPR_PATCHCONST; + + is_control_point = false; + if (!is_patch_constant) + { + switch (shader_type) + { + case VKD3D_SHADER_TYPE_DOMAIN: + case VKD3D_SHADER_TYPE_GEOMETRY: + is_control_point = is_input; + break; + + case VKD3D_SHADER_TYPE_HULL: + is_control_point = true; + break; + + default: + break; + } + } + for (i = 0; i < s->element_count; ++i) { e = &s->elements[i]; @@ -3709,8 +3740,18 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade dst_param_io_init(param, e, reg_type); count = 0; - if (e->register_count > 1) + + if (is_control_point) + { + if (reg_type == VKD3DSPR_OUTPUT) + param->reg.idx[count].rel_addr = instruction_array_create_outpointid_param(&sm6->p.program.instructions); + param->reg.idx[count++].offset = 0; + } + + if (e->register_count > 1 || (is_patch_constant && vsir_sysval_semantic_is_tess_factor(e->sysval_semantic))) param->reg.idx[count++].offset = 0; + + assert(count < ARRAY_SIZE(param->reg.idx)); param->reg.idx[count++].offset = i; param->reg.idx_count = count; } @@ -3718,12 +3759,21 @@ static void sm6_parser_init_signature(struct sm6_parser *sm6, const struct shade static void sm6_parser_init_output_signature(struct sm6_parser *sm6, const struct shader_signature *output_signature) { - sm6_parser_init_signature(sm6, output_signature, VKD3DSPR_OUTPUT, sm6->output_params); + sm6_parser_init_signature(sm6, output_signature, false, VKD3DSPR_OUTPUT, sm6->output_params); } static void sm6_parser_init_input_signature(struct sm6_parser *sm6, const struct shader_signature *input_signature) { - sm6_parser_init_signature(sm6, input_signature, VKD3DSPR_INPUT, sm6->input_params); + sm6_parser_init_signature(sm6, input_signature, true, VKD3DSPR_INPUT, sm6->input_params); +} + +static void sm6_parser_init_patch_constant_signature(struct sm6_parser *sm6, + const struct shader_signature *patch_constant_signature) +{ + bool is_input = sm6->p.program.shader_version.type == VKD3D_SHADER_TYPE_DOMAIN; + + sm6_parser_init_signature(sm6, patch_constant_signature, is_input, VKD3DSPR_PATCHCONST, + sm6->patch_constant_params); } static const struct sm6_value *sm6_parser_next_function_definition(struct sm6_parser *sm6) @@ -4752,6 +4802,33 @@ static void sm6_parser_emit_dx_discard(struct sm6_parser *sm6, enum dx_intrinsic src_param_init_from_value(src_param, operands[0]); } +static void sm6_parser_emit_dx_domain_location(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) +{ + struct vkd3d_shader_instruction *ins = state->ins; + struct vkd3d_shader_src_param *src_param; + unsigned int component_idx; + + vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); + + if ((component_idx = sm6_value_get_constant_uint(operands[0])) >= 3) + { + WARN("Invalid component index %u.\n", component_idx); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Invalid domain location component index %u.", component_idx); + component_idx = 0; + } + + if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) + return; + sm6_parser_dcl_register_builtin(sm6, VKD3DSIH_DCL_INPUT, VKD3DSPR_TESSCOORD, VKD3D_DATA_FLOAT, 3); + vsir_register_init(&src_param->reg, VKD3DSPR_TESSCOORD, VKD3D_DATA_FLOAT, 0); + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + src_param_init_scalar(src_param, component_idx); + + instruction_dst_param_init_ssa_scalar(ins, sm6); +} + static void sm6_parser_emit_dx_dot(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct function_emission_state *state) { @@ -4989,18 +5066,43 @@ static void sm6_parser_emit_dx_tertiary(struct sm6_parser *sm6, enum dx_intrinsi static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct function_emission_state *state) { + bool is_control_point = op == DX_LOAD_OUTPUT_CONTROL_POINT; + bool is_patch_constant = op == DX_LOAD_PATCH_CONSTANT; struct vkd3d_shader_instruction *ins = state->ins; + unsigned int count, row_index, column_index; + const struct vkd3d_shader_dst_param *params; struct vkd3d_shader_src_param *src_param; const struct shader_signature *signature; - unsigned int row_index, column_index; const struct signature_element *e; row_index = sm6_value_get_constant_uint(operands[0]); column_index = sm6_value_get_constant_uint(operands[2]); + if (is_control_point && operands[3]->is_undefined) + { + /* dxcompiler will compile source which does this, so let it pass. */ + WARN("Control point id is undefined.\n"); + vkd3d_shader_parser_warning(&sm6->p, VKD3D_SHADER_WARNING_DXIL_UNDEFINED_OPERAND, + "The index for a control point load is undefined."); + } + vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); - signature = &sm6->p.program.input_signature; + if (is_patch_constant) + { + signature = &sm6->p.program.patch_constant_signature; + params = sm6->patch_constant_params; + } + else if (is_control_point) + { + signature = &sm6->p.program.output_signature; + params = sm6->output_params; + } + else + { + signature = &sm6->p.program.input_signature; + params = sm6->input_params; + } if (row_index >= signature->element_count) { WARN("Invalid row index %u.\n", row_index); @@ -5012,10 +5114,18 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; - src_param->reg = sm6->input_params[row_index].reg; + src_param->reg = params[row_index].reg; src_param_init_scalar(src_param, column_index); + count = 0; + if (e->register_count > 1) - register_index_address_init(&src_param->reg.idx[0], operands[1], sm6); + register_index_address_init(&src_param->reg.idx[count++], operands[1], sm6); + + if (!is_patch_constant && !operands[3]->is_undefined) + { + assert(src_param->reg.idx_count > count); + register_index_address_init(&src_param->reg.idx[count], operands[3], sm6); + } instruction_dst_param_init_ssa_scalar(ins, sm6); } @@ -5040,6 +5150,12 @@ static void sm6_parser_emit_dx_make_double(struct sm6_parser *sm6, enum dx_intri instruction_dst_param_init_ssa_scalar(ins, sm6); } +static void sm6_parser_emit_dx_output_control_point_id(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) +{ + sm6_parser_emit_dx_input_register_mov(sm6, state->ins, VKD3DSPR_OUTPOINTID, VKD3D_DATA_UINT); +} + static void sm6_parser_emit_dx_primitive_id(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct function_emission_state *state) { @@ -5473,6 +5589,7 @@ static void sm6_parser_emit_dx_split_double(struct sm6_parser *sm6, enum dx_intr static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct function_emission_state *state) { + bool is_patch_constant = op == DX_STORE_PATCH_CONSTANT; struct vkd3d_shader_instruction *ins = state->ins; struct vkd3d_shader_src_param *src_param; struct vkd3d_shader_dst_param *dst_param; @@ -5484,7 +5601,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr row_index = sm6_value_get_constant_uint(operands[0]); column_index = sm6_value_get_constant_uint(operands[2]); - signature = &sm6->p.program.output_signature; + signature = is_patch_constant ? &sm6->p.program.patch_constant_signature : &sm6->p.program.output_signature; if (row_index >= signature->element_count) { WARN("Invalid row index %u.\n", row_index); @@ -5516,7 +5633,7 @@ static void sm6_parser_emit_dx_store_output(struct sm6_parser *sm6, enum dx_intr if (!(dst_param = instruction_dst_params_alloc(ins, 1, sm6))) return; dst_param_init_scalar(dst_param, column_index); - dst_param->reg = sm6->output_params[row_index].reg; + dst_param->reg = is_patch_constant ? sm6->patch_constant_params[row_index].reg : sm6->output_params[row_index].reg; if (e->register_count > 1) register_index_address_init(&dst_param->reg.idx[0], operands[1], sm6); @@ -5736,6 +5853,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_DERIV_FINEX ] = {"e", "R", sm6_parser_emit_dx_unary}, [DX_DERIV_FINEY ] = {"e", "R", sm6_parser_emit_dx_unary}, [DX_DISCARD ] = {"v", "1", sm6_parser_emit_dx_discard}, + [DX_DOMAIN_LOCATION ] = {"f", "c", sm6_parser_emit_dx_domain_location}, [DX_DOT2 ] = {"g", "RRRR", sm6_parser_emit_dx_dot}, [DX_DOT3 ] = {"g", "RRRRRR", sm6_parser_emit_dx_dot}, [DX_DOT4 ] = {"g", "RRRRRRRR", sm6_parser_emit_dx_dot}, @@ -5765,8 +5883,11 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_LEGACY_F16TOF32 ] = {"f", "i", sm6_parser_emit_dx_unary}, [DX_LEGACY_F32TOF16 ] = {"i", "f", sm6_parser_emit_dx_unary}, [DX_LOAD_INPUT ] = {"o", "ii8i", sm6_parser_emit_dx_load_input}, + [DX_LOAD_OUTPUT_CONTROL_POINT ] = {"o", "ii8i", sm6_parser_emit_dx_load_input}, + [DX_LOAD_PATCH_CONSTANT ] = {"o", "ii8", sm6_parser_emit_dx_load_input}, [DX_LOG ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_MAKE_DOUBLE ] = {"d", "ii", sm6_parser_emit_dx_make_double}, + [DX_OUTPUT_CONTROL_POINT_ID ] = {"i", "", sm6_parser_emit_dx_output_control_point_id}, [DX_PRIMITIVE_ID ] = {"i", "", sm6_parser_emit_dx_primitive_id}, [DX_RAW_BUFFER_LOAD ] = {"o", "Hii8i", sm6_parser_emit_dx_raw_buffer_load}, [DX_RAW_BUFFER_STORE ] = {"v", "Hiioooocc", sm6_parser_emit_dx_raw_buffer_store}, @@ -5788,6 +5909,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_SPLIT_DOUBLE ] = {"S", "d", sm6_parser_emit_dx_split_double}, [DX_SQRT ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_STORE_OUTPUT ] = {"v", "ii8o", sm6_parser_emit_dx_store_output}, + [DX_STORE_PATCH_CONSTANT ] = {"v", "ii8o", sm6_parser_emit_dx_store_output}, [DX_TAN ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_TEX2DMS_GET_SAMPLE_POS ] = {"o", "Hi", sm6_parser_emit_dx_get_sample_pos}, [DX_TEXTURE_GATHER ] = {"o", "HHffffiic", sm6_parser_emit_dx_texture_gather}, @@ -7286,11 +7408,6 @@ static enum vkd3d_result sm6_parser_function_init(struct sm6_parser *sm6, const struct sm6_block *code_block; struct sm6_value *dst; - if (sm6->function_count) - { - FIXME("Multiple functions are not supported yet.\n"); - return VKD3D_ERROR_INVALID_SHADER; - } if (!(function->declaration = sm6_parser_next_function_definition(sm6))) { WARN("Failed to find definition to match function body.\n"); @@ -8976,10 +9093,15 @@ static enum vkd3d_result sm6_parser_signatures_init(struct sm6_parser *sm6, cons { return ret; } - /* TODO: patch constant signature in operand 2. */ + if (m->u.node->operand_count > 1 && (ret = sm6_parser_read_signature(sm6, m->u.node->operands[2], + &sm6->p.program.patch_constant_signature, tessellator_domain)) < 0) + { + return ret; + } sm6_parser_init_input_signature(sm6, &sm6->p.program.input_signature); sm6_parser_init_output_signature(sm6, &sm6->p.program.output_signature); + sm6_parser_init_patch_constant_signature(sm6, &sm6->p.program.patch_constant_signature); return VKD3D_OK; } @@ -9509,9 +9631,10 @@ static struct sm6_function *sm6_parser_get_function(const struct sm6_parser *sm6 static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *source_name, struct vkd3d_shader_message_context *message_context, struct dxbc_shader_desc *dxbc_desc) { + size_t count, length, function_count, expected_function_count, byte_code_size = dxbc_desc->byte_code_size; + const struct shader_signature *patch_constant_signature = &sm6->p.program.patch_constant_signature; const struct shader_signature *output_signature = &sm6->p.program.output_signature; const struct shader_signature *input_signature = &sm6->p.program.input_signature; - size_t count, length, function_count, byte_code_size = dxbc_desc->byte_code_size; const struct vkd3d_shader_location location = {.source_name = source_name}; uint32_t version_token, dxil_version, token_count, magic; const uint32_t *byte_code = dxbc_desc->byte_code; @@ -9674,7 +9797,9 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou } if (!(sm6->output_params = vsir_program_get_dst_params(&sm6->p.program, output_signature->element_count)) - || !(sm6->input_params = vsir_program_get_dst_params(&sm6->p.program, input_signature->element_count))) + || !(sm6->input_params = vsir_program_get_dst_params(&sm6->p.program, input_signature->element_count)) + || !(sm6->patch_constant_params = vsir_program_get_dst_params(&sm6->p.program, + patch_constant_signature->element_count))) { ERR("Failed to allocate input/output parameters.\n"); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, @@ -9705,6 +9830,7 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou "Out of memory allocating DXIL value array."); return VKD3D_ERROR_OUT_OF_MEMORY; } + sm6->function_count = 0; sm6->ssa_next_id = 1; if ((ret = sm6_parser_globals_init(sm6)) < 0) @@ -9754,7 +9880,8 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou return ret; } - if (!sm6_parser_require_space(sm6, output_signature->element_count + input_signature->element_count)) + if (!sm6_parser_require_space(sm6, output_signature->element_count + input_signature->element_count + + patch_constant_signature->element_count)) { vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, "Out of memory emitting shader signature declarations."); @@ -9771,9 +9898,41 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const char *sou return VKD3D_ERROR_INVALID_SHADER; } - assert(sm6->function_count == 1); - if ((ret = sm6_function_emit_blocks(fn, sm6)) < 0) - return ret; + if (version.type == VKD3D_SHADER_TYPE_HULL) + { + sm6_parser_add_instruction(sm6, VKD3DSIH_HS_CONTROL_POINT_PHASE); + + if ((ret = sm6_function_emit_blocks(fn, sm6)) < 0) + return ret; + + if (!(fn = sm6_parser_get_function(sm6, sm6->patch_constant_function))) + { + WARN("Failed to find patch constant function '%s'.\n", sm6->patch_constant_function); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, + "Failed to find the patch constant function '%s' for a hull shader.", + sm6->patch_constant_function); + return VKD3D_ERROR_INVALID_SHADER; + } + + sm6_parser_add_instruction(sm6, VKD3DSIH_HS_FORK_PHASE); + if ((ret = sm6_function_emit_blocks(fn, sm6)) < 0) + return ret; + + expected_function_count = 2; + } + else + { + if ((ret = sm6_function_emit_blocks(fn, sm6)) < 0) + return ret; + expected_function_count = 1; + } + + if (sm6->function_count > expected_function_count) + { + FIXME("%zu unhandled functions.\n", sm6->function_count - expected_function_count); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_MODULE, + "%zu functions were not emitted.", sm6->function_count - expected_function_count); + } dxil_block_destroy(&sm6->root_block); diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c index 3e8dd2c486b..3e482a5fc70 100644 --- a/libs/vkd3d/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c @@ -79,6 +79,7 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *generator case VKD3DSIH_DCL_INPUT: case VKD3DSIH_DCL_OUTPUT: case VKD3DSIH_DCL_OUTPUT_SIV: + case VKD3DSIH_NOP: break; case VKD3DSIH_RET: shader_glsl_ret(generator, instruction); diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h index 7a8fe4de437..5e3010c4353 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h @@ -392,7 +392,7 @@ struct hlsl_attribute struct hlsl_reg_reservation { char reg_type; - unsigned int reg_index; + unsigned int reg_space, reg_index; char offset_type; unsigned int offset_index; diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y index 0c196b77595..f99f322d8d1 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y @@ -1197,17 +1197,18 @@ static bool add_effect_group(struct hlsl_ctx *ctx, const char *name, struct hlsl return true; } -static struct hlsl_reg_reservation parse_reg_reservation(const char *reg_string) +static bool parse_reservation_index(const char *string, char *type, uint32_t *index) { - struct hlsl_reg_reservation reservation = {0}; + if (!sscanf(string + 1, "%u", index)) + return false; - if (!sscanf(reg_string + 1, "%u", &reservation.reg_index)) - { - FIXME("Unsupported register reservation syntax.\n"); - return reservation; - } - reservation.reg_type = ascii_tolower(reg_string[0]); - return reservation; + *type = ascii_tolower(string[0]); + return true; +} + +static bool parse_reservation_space(const char *string, uint32_t *space) +{ + return !ascii_strncasecmp(string, "space", 5) && sscanf(string + 5, "%u", space); } static struct hlsl_reg_reservation parse_packoffset(struct hlsl_ctx *ctx, const char *reg_string, @@ -5675,8 +5676,8 @@ static bool state_block_add_entry(struct hlsl_state_block *state_block, struct h %type param_list %type parameters -%type register_opt -%type packoffset_opt +%type register_reservation +%type packoffset_reservation %type texture_type texture_ms_type uav_type rov_type @@ -6300,12 +6301,12 @@ colon_attribute: $$.reg_reservation.reg_type = 0; $$.reg_reservation.offset_type = 0; } - | register_opt + | register_reservation { $$.semantic = (struct hlsl_semantic){0}; $$.reg_reservation = $1; } - | packoffset_opt + | packoffset_reservation { $$.semantic = (struct hlsl_semantic){0}; $$.reg_reservation = $1; @@ -6327,22 +6328,57 @@ semantic: } /* FIXME: Writemasks */ -register_opt: +register_reservation: ':' KW_REGISTER '(' any_identifier ')' { - $$ = parse_reg_reservation($4); + memset(&$$, 0, sizeof($$)); + if (!parse_reservation_index($4, &$$.reg_type, &$$.reg_index)) + hlsl_error(ctx, &@4, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, + "Invalid register reservation '%s'.", $4); + vkd3d_free($4); } | ':' KW_REGISTER '(' any_identifier ',' any_identifier ')' { - FIXME("Ignoring shader target %s in a register reservation.\n", debugstr_a($4)); + memset(&$$, 0, sizeof($$)); + if (parse_reservation_index($6, &$$.reg_type, &$$.reg_index)) + { + hlsl_fixme(ctx, &@4, "Reservation shader target %s.", $4); + } + else if (parse_reservation_space($6, &$$.reg_space)) + { + if (!parse_reservation_index($4, &$$.reg_type, &$$.reg_index)) + hlsl_error(ctx, &@4, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, + "Invalid register reservation '%s'.", $4); + } + else + { + hlsl_error(ctx, &@6, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, + "Invalid register or space reservation '%s'.", $6); + } + vkd3d_free($4); + vkd3d_free($6); + } + | ':' KW_REGISTER '(' any_identifier ',' any_identifier ',' any_identifier ')' + { + hlsl_fixme(ctx, &@4, "Reservation shader target %s.", $4); - $$ = parse_reg_reservation($6); + memset(&$$, 0, sizeof($$)); + if (!parse_reservation_index($6, &$$.reg_type, &$$.reg_index)) + hlsl_error(ctx, &@6, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, + "Invalid register reservation '%s'.", $6); + + if (!parse_reservation_space($8, &$$.reg_space)) + hlsl_error(ctx, &@8, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, + "Invalid register space reservation '%s'.", $8); + + vkd3d_free($4); vkd3d_free($6); + vkd3d_free($8); } -packoffset_opt: +packoffset_reservation: ':' KW_PACKOFFSET '(' any_identifier ')' { $$ = parse_packoffset(ctx, $4, NULL, &@$); diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c index eca18f4eb28..1f8d60c62ac 100644 --- a/libs/vkd3d/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d/libs/vkd3d-shader/ir.c @@ -636,11 +636,14 @@ static bool control_point_normaliser_is_in_control_point_phase(const struct cont return normaliser->phase == VKD3DSIH_HS_CONTROL_POINT_PHASE; } -static struct vkd3d_shader_src_param *instruction_array_create_outpointid_param( +struct vkd3d_shader_src_param *instruction_array_create_outpointid_param( struct vkd3d_shader_instruction_array *instructions) { struct vkd3d_shader_src_param *rel_addr; + if (instructions->outpointid_param) + return instructions->outpointid_param; + if (!(rel_addr = shader_src_param_allocator_get(&instructions->src_params, 1))) return NULL; @@ -648,6 +651,7 @@ static struct vkd3d_shader_src_param *instruction_array_create_outpointid_param( rel_addr->swizzle = 0; rel_addr->modifiers = 0; + instructions->outpointid_param = rel_addr; return rel_addr; } @@ -3344,6 +3348,14 @@ static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program enum vkd3d_result ret; size_t i; + if (program->shader_version.type == VKD3D_SHADER_TYPE_HULL) + { + FIXME("Hull shaders are not supported.\n"); + vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, + "The structurizer does not support hull shaders."); + return VKD3D_ERROR_INVALID_SHADER; + } + memset(cfg, 0, sizeof(*cfg)); cfg->message_context = message_context; cfg->program = program; diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h index 1f4320968d3..4434e6e98f2 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h @@ -202,6 +202,7 @@ enum vkd3d_shader_error VKD3D_SHADER_WARNING_DXIL_INVALID_MASK = 8307, VKD3D_SHADER_WARNING_DXIL_INVALID_OPERATION = 8308, VKD3D_SHADER_WARNING_DXIL_IGNORING_ATTACHMENT = 8309, + VKD3D_SHADER_WARNING_DXIL_UNDEFINED_OPERAND = 8310, VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED = 9000, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER = 9001, @@ -1300,6 +1301,8 @@ struct vkd3d_shader_instruction_array struct vkd3d_shader_immediate_constant_buffer **icbs; size_t icb_capacity; size_t icb_count; + + struct vkd3d_shader_src_param *outpointid_param; }; bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve); @@ -1310,6 +1313,8 @@ bool shader_instruction_array_add_icb(struct vkd3d_shader_instruction_array *ins struct vkd3d_shader_immediate_constant_buffer *icb); bool shader_instruction_array_clone_instruction(struct vkd3d_shader_instruction_array *instructions, unsigned int dst, unsigned int src); +struct vkd3d_shader_src_param *instruction_array_create_outpointid_param( + struct vkd3d_shader_instruction_array *instructions); void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *instructions); enum vkd3d_shader_config_flags diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h index e0a7acb306d..5f60c8d90ad 100644 --- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h @@ -24,10 +24,6 @@ #define VK_NO_PROTOTYPES #define CONST_VTABLE -#ifdef _WIN32 -# define _WIN32_WINNT 0x0600 /* for condition variables */ -#endif - #include "vkd3d_common.h" #include "vkd3d_blob.h" #include "vkd3d_memory.h" @@ -205,36 +201,6 @@ union vkd3d_thread_handle void *handle; }; -struct vkd3d_cond -{ - CONDITION_VARIABLE cond; -}; - -static inline void vkd3d_cond_init(struct vkd3d_cond *cond) -{ - InitializeConditionVariable(&cond->cond); -} - -static inline void vkd3d_cond_signal(struct vkd3d_cond *cond) -{ - WakeConditionVariable(&cond->cond); -} - -static inline void vkd3d_cond_broadcast(struct vkd3d_cond *cond) -{ - WakeAllConditionVariable(&cond->cond); -} - -static inline void vkd3d_cond_wait(struct vkd3d_cond *cond, struct vkd3d_mutex *lock) -{ - if (!SleepConditionVariableCS(&cond->cond, &lock->lock, INFINITE)) - ERR("Could not sleep on the condition variable, error %lu.\n", GetLastError()); -} - -static inline void vkd3d_cond_destroy(struct vkd3d_cond *cond) -{ -} - static inline bool vkd3d_atomic_compare_exchange(unsigned int volatile *x, unsigned int cmp, unsigned int xchg) { return InterlockedCompareExchange((LONG volatile *)x, xchg, cmp) == cmp; @@ -265,56 +231,6 @@ union vkd3d_thread_handle void *handle; }; -struct vkd3d_cond -{ - pthread_cond_t cond; -}; - -static inline void vkd3d_cond_init(struct vkd3d_cond *cond) -{ - int ret; - - ret = pthread_cond_init(&cond->cond, NULL); - if (ret) - ERR("Could not initialize the condition variable, error %d.\n", ret); -} - -static inline void vkd3d_cond_signal(struct vkd3d_cond *cond) -{ - int ret; - - ret = pthread_cond_signal(&cond->cond); - if (ret) - ERR("Could not signal the condition variable, error %d.\n", ret); -} - -static inline void vkd3d_cond_broadcast(struct vkd3d_cond *cond) -{ - int ret; - - ret = pthread_cond_broadcast(&cond->cond); - if (ret) - ERR("Could not broadcast the condition variable, error %d.\n", ret); -} - -static inline void vkd3d_cond_wait(struct vkd3d_cond *cond, struct vkd3d_mutex *lock) -{ - int ret; - - ret = pthread_cond_wait(&cond->cond, &lock->lock); - if (ret) - ERR("Could not wait on the condition variable, error %d.\n", ret); -} - -static inline void vkd3d_cond_destroy(struct vkd3d_cond *cond) -{ - int ret; - - ret = pthread_cond_destroy(&cond->cond); - if (ret) - ERR("Could not destroy the condition variable, error %d.\n", ret); -} - # if HAVE_SYNC_BOOL_COMPARE_AND_SWAP static inline bool vkd3d_atomic_compare_exchange(unsigned int volatile *x, unsigned int cmp, unsigned int xchg) { -- 2.43.0