From 512ffa3af40d1fab9d76cfff8b26d6b60c4481ac Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Thu, 1 Feb 2024 12:20:04 +1100 Subject: [PATCH 2/5] Updated vkd3d to 6dea3d08b1e9453bfc51dfec827cf1a25c2729df. --- libs/vkd3d/include/private/vkd3d_debug.h | 4 + libs/vkd3d/include/vkd3d_d3dcompiler.h | 4 + libs/vkd3d/include/vkd3d_shader.h | 8 +- libs/vkd3d/include/vkd3d_utils.h | 2 + libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 17 +- libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 15 +- libs/vkd3d/libs/vkd3d-shader/dxil.c | 170 ++++++++- libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 137 +++++-- libs/vkd3d/libs/vkd3d-shader/ir.c | 334 +++++++++++++++++- libs/vkd3d/libs/vkd3d-shader/spirv.c | 56 ++- libs/vkd3d/libs/vkd3d-shader/tpf.c | 10 +- .../libs/vkd3d-shader/vkd3d_shader_main.c | 4 +- .../libs/vkd3d-shader/vkd3d_shader_private.h | 108 ++++-- libs/vkd3d/libs/vkd3d/device.c | 12 +- libs/vkd3d/libs/vkd3d/resource.c | 24 +- libs/vkd3d/libs/vkd3d/vkd3d_private.h | 16 +- 16 files changed, 767 insertions(+), 154 deletions(-) diff --git a/libs/vkd3d/include/private/vkd3d_debug.h b/libs/vkd3d/include/private/vkd3d_debug.h index 663fc311adf..c5b6ccedf81 100644 --- a/libs/vkd3d/include/private/vkd3d_debug.h +++ b/libs/vkd3d/include/private/vkd3d_debug.h @@ -89,6 +89,10 @@ const char *debugstr_w(const WCHAR *wstr, size_t wchar_size); #define TRACE_ON() (vkd3d_dbg_get_level() == VKD3D_DBG_LEVEL_TRACE) #endif +#ifndef WARN_ON +#define WARN_ON() (vkd3d_dbg_get_level() >= VKD3D_DBG_LEVEL_WARN) +#endif + #define FIXME_ONCE VKD3D_DBG_LOG_ONCE(FIXME, WARN) #define VKD3D_DEBUG_ENV_NAME(name) const char *const vkd3d_dbg_env_name = name diff --git a/libs/vkd3d/include/vkd3d_d3dcompiler.h b/libs/vkd3d/include/vkd3d_d3dcompiler.h index 1975f4f980a..872a90bbc4b 100644 --- a/libs/vkd3d/include/vkd3d_d3dcompiler.h +++ b/libs/vkd3d/include/vkd3d_d3dcompiler.h @@ -79,6 +79,7 @@ HRESULT WINAPI D3DCompile2(const void *data, SIZE_T data_size, const char *filen const void *secondary_data, SIZE_T secondary_data_size, ID3DBlob **shader, ID3DBlob **error_messages); HRESULT WINAPI D3DCreateBlob(SIZE_T size, ID3DBlob **blob); +HRESULT WINAPI D3DDisassemble(const void *data, SIZE_T data_size, UINT flags, const char *comments, ID3DBlob **blob); HRESULT WINAPI D3DGetBlobPart(const void *data, SIZE_T data_size, D3D_BLOB_PART part, UINT flags, ID3DBlob **blob); HRESULT WINAPI D3DGetDebugInfo(const void *data, SIZE_T data_size, ID3DBlob **blob); HRESULT WINAPI D3DGetInputAndOutputSignatureBlob(const void *data, SIZE_T data_size, ID3DBlob **blob); @@ -89,5 +90,8 @@ HRESULT WINAPI D3DPreprocess(const void *data, SIZE_T size, const char *filename HRESULT WINAPI D3DReflect(const void *data, SIZE_T data_size, REFIID iid, void **reflection); HRESULT WINAPI D3DStripShader(const void *data, SIZE_T data_size, UINT flags, ID3DBlob **blob); +typedef HRESULT (WINAPI *pD3DDisassemble)(const void *data, SIZE_T data_size, + UINT flags, const char *comments, ID3DBlob **blob); + #endif /* __D3DCOMPILER_H__ */ #endif /* __VKD3D_D3DCOMPILER_H */ diff --git a/libs/vkd3d/include/vkd3d_shader.h b/libs/vkd3d/include/vkd3d_shader.h index a8cc3a336a3..2f4478a7983 100644 --- a/libs/vkd3d/include/vkd3d_shader.h +++ b/libs/vkd3d/include/vkd3d_shader.h @@ -1777,10 +1777,10 @@ struct vkd3d_shader_dxbc_desc * \endcode */ #define VKD3D_SHADER_SWIZZLE(x, y, z, w) \ - vkd3d_shader_create_swizzle(VKD3D_SHADER_SWIZZLE_ ## x, \ - VKD3D_SHADER_SWIZZLE_ ## y, \ - VKD3D_SHADER_SWIZZLE_ ## z, \ - VKD3D_SHADER_SWIZZLE_ ## w) + (VKD3D_SHADER_SWIZZLE_ ## x << VKD3D_SHADER_SWIZZLE_SHIFT(0) \ + | VKD3D_SHADER_SWIZZLE_ ## y << VKD3D_SHADER_SWIZZLE_SHIFT(1) \ + | VKD3D_SHADER_SWIZZLE_ ## z << VKD3D_SHADER_SWIZZLE_SHIFT(2) \ + | VKD3D_SHADER_SWIZZLE_ ## w << VKD3D_SHADER_SWIZZLE_SHIFT(3)) /** The identity swizzle ".xyzw". */ #define VKD3D_SHADER_NO_SWIZZLE VKD3D_SHADER_SWIZZLE(X, Y, Z, W) diff --git a/libs/vkd3d/include/vkd3d_utils.h b/libs/vkd3d/include/vkd3d_utils.h index adcac5fcf64..7616a3f3c46 100644 --- a/libs/vkd3d/include/vkd3d_utils.h +++ b/libs/vkd3d/include/vkd3d_utils.h @@ -117,6 +117,8 @@ VKD3D_UTILS_API HRESULT WINAPI D3DGetOutputSignatureBlob(const void *data, SIZE_ VKD3D_UTILS_API HRESULT WINAPI D3DStripShader(const void *data, SIZE_T data_size, UINT flags, ID3DBlob **blob); /** \since 1.11 */ +VKD3D_UTILS_API HRESULT WINAPI D3DDisassemble(const void *data, + SIZE_T data_size, UINT flags, const char *comments, ID3DBlob **blob); VKD3D_UTILS_API HRESULT WINAPI D3DReflect(const void *data, SIZE_T data_size, REFIID iid, void **reflection); #ifdef __cplusplus diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c index af939396a08..dd96b7fa50b 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c @@ -1389,7 +1389,7 @@ static void shader_dump_dst_param(struct vkd3d_d3d_asm_compiler *compiler, { static const char write_mask_chars[] = "xyzw"; - if (param->reg.data_type == VKD3D_DATA_DOUBLE) + if (data_type_is_64_bit(param->reg.data_type)) write_mask = vsir_write_mask_32_from_64(write_mask); shader_addline(buffer, ".%s", compiler->colours.write_mask); @@ -1454,13 +1454,18 @@ static void shader_dump_src_param(struct vkd3d_d3d_asm_compiler *compiler, if (param->reg.type != VKD3DSPR_IMMCONST && param->reg.type != VKD3DSPR_IMMCONST64 && param->reg.dimension == VSIR_DIMENSION_VEC4) { - unsigned int swizzle_x = vsir_swizzle_get_component(swizzle, 0); - unsigned int swizzle_y = vsir_swizzle_get_component(swizzle, 1); - unsigned int swizzle_z = vsir_swizzle_get_component(swizzle, 2); - unsigned int swizzle_w = vsir_swizzle_get_component(swizzle, 3); - static const char swizzle_chars[] = "xyzw"; + unsigned int swizzle_x, swizzle_y, swizzle_z, swizzle_w; + + if (data_type_is_64_bit(param->reg.data_type)) + swizzle = vsir_swizzle_32_from_64(swizzle); + + swizzle_x = vsir_swizzle_get_component(swizzle, 0); + swizzle_y = vsir_swizzle_get_component(swizzle, 1); + swizzle_z = vsir_swizzle_get_component(swizzle, 2); + swizzle_w = vsir_swizzle_get_component(swizzle, 3); + if (swizzle_x == swizzle_y && swizzle_x == swizzle_z && swizzle_x == swizzle_w) diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c index 4ba001ea4cd..9ad9f735dd1 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c @@ -587,7 +587,7 @@ static void add_signature_mask(struct vkd3d_shader_sm1_parser *sm1, bool output, if (!(element = find_signature_element_by_register_index(signature, register_index))) { - vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_UNDECLARED_SEMANTIC, + vkd3d_shader_parser_warning(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_UNDECLARED_SEMANTIC, "%s register %u was used without being declared.", output ? "Output" : "Input", register_index); return; } @@ -899,7 +899,7 @@ static void shader_sm1_read_src_param(struct vkd3d_shader_sm1_parser *sm1, const shader_sm1_read_param(sm1, ptr, &token, &addr_token); if (has_relative_address(token)) { - if (!(src_rel_addr = shader_parser_get_src_params(&sm1->p, 1))) + if (!(src_rel_addr = vsir_program_get_src_params(&sm1->p.program, 1))) { vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, "Out of memory."); @@ -920,7 +920,7 @@ static void shader_sm1_read_dst_param(struct vkd3d_shader_sm1_parser *sm1, const shader_sm1_read_param(sm1, ptr, &token, &addr_token); if (has_relative_address(token)) { - if (!(dst_rel_addr = shader_parser_get_src_params(&sm1->p, 1))) + if (!(dst_rel_addr = vsir_program_get_src_params(&sm1->p.program, 1))) { vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, "Out of memory."); @@ -1089,6 +1089,7 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str { struct vkd3d_shader_src_param *src_params, *predicate; const struct vkd3d_sm1_opcode_info *opcode_info; + struct vsir_program *program = &sm1->p.program; struct vkd3d_shader_dst_param *dst_param; const uint32_t **ptr = &sm1->ptr; uint32_t opcode_token; @@ -1111,7 +1112,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.program.shader_version.major, sm1->p.program.shader_version.minor); + program->shader_version.major, program->shader_version.minor); goto fail; } @@ -1121,11 +1122,11 @@ static void shader_sm1_read_instruction(struct vkd3d_shader_sm1_parser *sm1, str ins->raw = false; ins->structured = false; predicated = !!(opcode_token & VKD3D_SM1_INSTRUCTION_PREDICATED); - ins->predicate = predicate = predicated ? shader_parser_get_src_params(&sm1->p, 1) : NULL; + ins->predicate = predicate = predicated ? vsir_program_get_src_params(program, 1) : NULL; ins->dst_count = opcode_info->dst_count; - ins->dst = dst_param = shader_parser_get_dst_params(&sm1->p, ins->dst_count); + ins->dst = dst_param = vsir_program_get_dst_params(program, ins->dst_count); ins->src_count = opcode_info->src_count; - ins->src = src_params = shader_parser_get_src_params(&sm1->p, ins->src_count); + ins->src = src_params = vsir_program_get_src_params(program, ins->src_count); if ((!predicate && predicated) || (!src_params && ins->src_count) || (!dst_param && ins->dst_count)) { vkd3d_shader_parser_error(&sm1->p, VKD3D_SHADER_ERROR_D3DBC_OUT_OF_MEMORY, "Out of memory."); diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c index 8a31d03c531..0358dbb6e06 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c @@ -36,6 +36,10 @@ static const unsigned int SHADER_DESCRIPTOR_TYPE_COUNT = 4; static const unsigned int dx_max_thread_group_size[3] = {1024, 1024, 64}; +#define VKD3D_SHADER_SWIZZLE_64_MASK \ + (VKD3D_SHADER_SWIZZLE_MASK << VKD3D_SHADER_SWIZZLE_SHIFT(0) \ + | VKD3D_SHADER_SWIZZLE_MASK << VKD3D_SHADER_SWIZZLE_SHIFT(1)) + enum bitcode_block_id { BLOCKINFO_BLOCK = 0, @@ -354,6 +358,8 @@ enum dx_intrinsic_opcode DX_IMIN = 38, DX_UMAX = 39, DX_UMIN = 40, + DX_IBFE = 51, + DX_UBFE = 52, DX_CREATE_HANDLE = 57, DX_CBUFFER_LOAD_LEGACY = 59, DX_BUFFER_LOAD = 68, @@ -363,6 +369,7 @@ enum dx_intrinsic_opcode DX_DERIV_FINEY = 86, DX_LEGACY_F32TOF16 = 130, DX_LEGACY_F16TOF32 = 131, + DX_RAW_BUFFER_LOAD = 139, }; enum dxil_cast_code @@ -2078,13 +2085,16 @@ static void instruction_init_with_resource(struct vkd3d_shader_instruction *ins, { vsir_instruction_init(ins, &sm6->p.location, handler_idx); ins->resource_type = resource->u.handle.d->resource_type; + ins->raw = resource->u.handle.d->kind == RESOURCE_KIND_RAWBUFFER; + ins->structured = resource->u.handle.d->kind == RESOURCE_KIND_STRUCTUREDBUFFER; } static struct vkd3d_shader_src_param *instruction_src_params_alloc(struct vkd3d_shader_instruction *ins, unsigned int count, struct sm6_parser *sm6) { - struct vkd3d_shader_src_param *params = shader_parser_get_src_params(&sm6->p, count); - if (!params) + struct vkd3d_shader_src_param *params; + + if (!(params = vsir_program_get_src_params(&sm6->p.program, count))) { ERR("Failed to allocate src params.\n"); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, @@ -2099,8 +2109,9 @@ static struct vkd3d_shader_src_param *instruction_src_params_alloc(struct vkd3d_ static struct vkd3d_shader_dst_param *instruction_dst_params_alloc(struct vkd3d_shader_instruction *ins, unsigned int count, struct sm6_parser *sm6) { - struct vkd3d_shader_dst_param *params = shader_parser_get_dst_params(&sm6->p, count); - if (!params) + struct vkd3d_shader_dst_param *params; + + if (!(params = vsir_program_get_dst_params(&sm6->p.program, count))) { ERR("Failed to allocate dst params.\n"); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, @@ -2211,6 +2222,8 @@ static inline void src_param_init(struct vkd3d_shader_src_param *param) static void src_param_init_scalar(struct vkd3d_shader_src_param *param, unsigned int component_idx) { param->swizzle = vkd3d_shader_create_swizzle(component_idx, component_idx, component_idx, component_idx); + if (data_type_is_64_bit(param->reg.data_type)) + param->swizzle &= VKD3D_SHADER_SWIZZLE_64_MASK; param->modifiers = VKD3DSPSM_NONE; } @@ -2241,7 +2254,7 @@ static void register_index_address_init(struct vkd3d_shader_register_index *idx, } else { - struct vkd3d_shader_src_param *rel_addr = shader_parser_get_src_params(&sm6->p, 1); + struct vkd3d_shader_src_param *rel_addr = vsir_program_get_src_params(&sm6->p.program, 1); if (rel_addr) src_param_init_from_value(rel_addr, address); idx->offset = 0; @@ -3100,6 +3113,15 @@ static void dst_param_io_init(struct vkd3d_shader_dst_param *param, param->reg.dimension = VSIR_DIMENSION_VEC4; } +static void src_params_init_from_operands(struct vkd3d_shader_src_param *src_params, + const struct sm6_value **operands, unsigned int count) +{ + unsigned int i; + + for (i = 0; i < count; ++i) + src_param_init_from_value(&src_params[i], operands[i]); +} + 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) { @@ -3624,6 +3646,8 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr type = sm6_type_get_scalar_type(dst->type, 0); assert(type); src_param->reg.data_type = vkd3d_data_type_from_sm6_type(type); + if (data_type_is_64_bit(src_param->reg.data_type)) + src_param->swizzle = vsir_swizzle_64_from_32(src_param->swizzle); instruction_dst_param_init_ssa_vector(ins, sm6_type_max_vector_size(type), sm6); } @@ -3689,6 +3713,34 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int ins->handler_idx = VKD3DSIH_NOP; } +static enum vkd3d_shader_opcode sm6_dx_map_tertiary_op(enum dx_intrinsic_opcode op) +{ + switch (op) + { + case DX_IBFE: + return VKD3DSIH_IBFE; + case DX_UBFE: + return VKD3DSIH_UBFE; + default: + vkd3d_unreachable(); + } +} + +static void sm6_parser_emit_dx_tertiary(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_params; + unsigned int i; + + vsir_instruction_init(ins, &sm6->p.location, sm6_dx_map_tertiary_op(op)); + src_params = instruction_src_params_alloc(ins, 3, sm6); + for (i = 0; i < 3; ++i) + src_param_init_from_value(&src_params[i], operands[i]); + + instruction_dst_param_init_ssa_scalar(ins, sm6); +} + 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) { @@ -3722,6 +3774,49 @@ static void sm6_parser_emit_dx_load_input(struct sm6_parser *sm6, enum dx_intrin instruction_dst_param_init_ssa_scalar(ins, sm6); } +static void sm6_parser_emit_dx_raw_buffer_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) +{ + unsigned int operand_count, write_mask, component_count = VKD3D_VEC4_SIZE; + struct vkd3d_shader_instruction *ins = state->ins; + struct vkd3d_shader_src_param *src_params; + const struct sm6_value *resource; + bool raw; + + resource = operands[0]; + if (!sm6_value_validate_is_handle(resource, sm6)) + return; + raw = resource->u.handle.d->kind == RESOURCE_KIND_RAWBUFFER; + + if (op == DX_RAW_BUFFER_LOAD) + { + write_mask = sm6_value_get_constant_uint(operands[3]); + if (!write_mask || write_mask > VKD3DSP_WRITEMASK_ALL) + { + WARN("Invalid write mask %#x.\n", write_mask); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Write mask %#x for a raw/structured buffer load operation is invalid.", write_mask); + return; + } + else if (write_mask & (write_mask + 1)) + { + FIXME("Unhandled write mask %#x.\n", write_mask); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Write mask %#x for a raw/structured buffer load operation is unhandled.", write_mask); + } + component_count = vsir_write_mask_component_count(write_mask); + } + + instruction_init_with_resource(ins, raw ? VKD3DSIH_LD_RAW : VKD3DSIH_LD_STRUCTURED, resource, sm6); + operand_count = 2 + !raw; + if (!(src_params = instruction_src_params_alloc(ins, operand_count, sm6))) + return; + src_params_init_from_operands(src_params, &operands[1], operand_count - 1); + src_param_init_vector_from_reg(&src_params[operand_count - 1], &resource->u.handle.reg); + + instruction_dst_param_init_ssa_vector(ins, component_count, sm6); +} + static void sm6_parser_emit_dx_buffer_load(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct function_emission_state *state) { @@ -3733,6 +3828,12 @@ static void sm6_parser_emit_dx_buffer_load(struct sm6_parser *sm6, enum dx_intri if (!sm6_value_validate_is_handle(resource, sm6)) return; + if (resource->u.handle.d->kind == RESOURCE_KIND_RAWBUFFER + || resource->u.handle.d->kind == RESOURCE_KIND_STRUCTUREDBUFFER) + { + return sm6_parser_emit_dx_raw_buffer_load(sm6, op, operands, state); + } + if (resource->u.handle.d->kind != RESOURCE_KIND_TYPEDBUFFER) { WARN("Resource is not a typed buffer.\n"); @@ -3875,6 +3976,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_FMAX ] = {"g", "RR", sm6_parser_emit_dx_binary}, [DX_FMIN ] = {"g", "RR", sm6_parser_emit_dx_binary}, [DX_FRC ] = {"g", "R", sm6_parser_emit_dx_unary}, + [DX_IBFE ] = {"m", "iiR", sm6_parser_emit_dx_tertiary}, [DX_IMAX ] = {"m", "RR", sm6_parser_emit_dx_binary}, [DX_IMIN ] = {"m", "RR", sm6_parser_emit_dx_binary}, [DX_ISFINITE ] = {"1", "g", sm6_parser_emit_dx_unary}, @@ -3884,6 +3986,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_LEGACY_F32TOF16 ] = {"i", "f", sm6_parser_emit_dx_unary}, [DX_LOAD_INPUT ] = {"o", "ii8i", sm6_parser_emit_dx_load_input}, [DX_LOG ] = {"g", "R", sm6_parser_emit_dx_unary}, + [DX_RAW_BUFFER_LOAD ] = {"o", "Hii8i", sm6_parser_emit_dx_raw_buffer_load}, [DX_ROUND_NE ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_ROUND_NI ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_ROUND_PI ] = {"g", "R", sm6_parser_emit_dx_unary}, @@ -3893,6 +3996,7 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_SQRT ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_STORE_OUTPUT ] = {"v", "ii8o", sm6_parser_emit_dx_store_output}, [DX_TAN ] = {"g", "R", sm6_parser_emit_dx_unary}, + [DX_UBFE ] = {"m", "iiR", sm6_parser_emit_dx_tertiary}, [DX_UMAX ] = {"m", "RR", sm6_parser_emit_dx_binary}, [DX_UMIN ] = {"m", "RR", sm6_parser_emit_dx_binary}, }; @@ -4444,8 +4548,8 @@ static void sm6_parser_emit_extractval(struct sm6_parser *sm6, const struct dxil vsir_instruction_init(ins, &sm6->p.location, VKD3DSIH_MOV); src_param = instruction_src_params_alloc(ins, 1, sm6); - src_param_init_from_value(src_param, src); - src_param->swizzle = vkd3d_shader_create_swizzle(elem_idx, elem_idx, elem_idx, elem_idx); + src_param_init_scalar(src_param, elem_idx); + src_param->reg = src->u.reg; instruction_dst_param_init_ssa_scalar(ins, sm6); } @@ -5975,6 +6079,8 @@ static enum vkd3d_shader_resource_type shader_resource_type_from_dxil_resource_k switch (kind) { case RESOURCE_KIND_TYPEDBUFFER: + case RESOURCE_KIND_RAWBUFFER: + case RESOURCE_KIND_STRUCTUREDBUFFER: return VKD3D_SHADER_RESOURCE_BUFFER; default: return VKD3D_SHADER_RESOURCE_NONE; @@ -6039,6 +6145,13 @@ static struct vkd3d_shader_resource *sm6_parser_resources_load_common_info(struc } ins->resource_type = resource_type; + if (!m) + { + ins->handler_idx = is_uav ? VKD3DSIH_DCL_UAV_RAW : VKD3DSIH_DCL_RESOURCE_RAW; + ins->declaration.raw_resource.resource.reg.write_mask = 0; + return &ins->declaration.raw_resource.resource; + } + if (!sm6_metadata_value_is_node(m)) { WARN("Resource metadata list is not a node.\n"); @@ -6093,6 +6206,39 @@ static struct vkd3d_shader_resource *sm6_parser_resources_load_common_info(struc return &ins->declaration.semantic.resource; } + else if (dxil_resource_type == RESOURCE_TYPE_RAW_STRUCTURED) + { + if (kind == RESOURCE_KIND_RAWBUFFER) + { + ins->handler_idx = is_uav ? VKD3DSIH_DCL_UAV_RAW : VKD3DSIH_DCL_RESOURCE_RAW; + ins->declaration.raw_resource.resource.reg.write_mask = 0; + + return &ins->declaration.raw_resource.resource; + } + + if (kind != RESOURCE_KIND_STRUCTUREDBUFFER) + { + WARN("Unhandled resource kind %u.\n", kind); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, + "Resource kind %u for a raw or structured buffer is unhandled.", kind); + return NULL; + } + + ins->handler_idx = is_uav ? VKD3DSIH_DCL_UAV_STRUCTURED : VKD3DSIH_DCL_RESOURCE_STRUCTURED; + ins->declaration.structured_resource.byte_stride = values[1]; + ins->declaration.structured_resource.resource.reg.write_mask = 0; + + /* TODO: 16-bit resources. */ + if (ins->declaration.structured_resource.byte_stride % 4u) + { + WARN("Byte stride %u is not a multiple of 4.\n", ins->declaration.structured_resource.byte_stride); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_RESOURCES, + "Structured resource byte stride %u is not a multiple of 4.", + ins->declaration.structured_resource.byte_stride); + } + + return &ins->declaration.structured_resource.resource; + } else { FIXME("Unhandled resource type %u.\n", dxil_resource_type); @@ -6159,7 +6305,8 @@ static enum vkd3d_result sm6_parser_resources_load_srv(struct sm6_parser *sm6, d->kind = kind; d->reg_type = VKD3DSPR_RESOURCE; d->reg_data_type = (ins->resource_type == VKD3D_SHADER_RESOURCE_BUFFER) ? VKD3D_DATA_UINT : VKD3D_DATA_RESOURCE; - d->resource_data_type = ins->declaration.semantic.resource_data_type[0]; + d->resource_data_type = (ins->handler_idx == VKD3DSIH_DCL) + ? ins->declaration.semantic.resource_data_type[0] : VKD3D_DATA_UNUSED; init_resource_declaration(resource, VKD3DSPR_RESOURCE, d->reg_data_type, d->id, &d->range); @@ -6232,7 +6379,8 @@ static enum vkd3d_result sm6_parser_resources_load_uav(struct sm6_parser *sm6, d->kind = values[0]; d->reg_type = VKD3DSPR_UAV; d->reg_data_type = (ins->resource_type == VKD3D_SHADER_RESOURCE_BUFFER) ? VKD3D_DATA_UINT : VKD3D_DATA_UAV; - d->resource_data_type = ins->declaration.semantic.resource_data_type[0]; + d->resource_data_type = (ins->handler_idx == VKD3DSIH_DCL_UAV_TYPED) + ? ins->declaration.semantic.resource_data_type[0] : VKD3D_DATA_UNUSED; init_resource_declaration(resource, VKD3DSPR_UAV, d->reg_data_type, d->id, &d->range); @@ -7165,8 +7313,8 @@ static enum vkd3d_result sm6_parser_init(struct sm6_parser *sm6, const uint32_t return ret; } - if (!(sm6->output_params = shader_parser_get_dst_params(&sm6->p, output_signature->element_count)) - || !(sm6->input_params = shader_parser_get_dst_params(&sm6->p, input_signature->element_count))) + 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))) { ERR("Failed to allocate input/output parameters.\n"); vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_OUT_OF_MEMORY, diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c index 1fe141a346a..6ad60e4c6c2 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c @@ -4123,13 +4123,46 @@ static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_functi LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { - if (var->is_uniform && var->last_read) + unsigned int reg_size = var->data_type->reg_size[HLSL_REGSET_NUMERIC]; + + if (!var->is_uniform || !var->last_read || reg_size == 0) + continue; + + if (var->reg_reservation.reg_type == 'c') { - unsigned int reg_size = var->data_type->reg_size[HLSL_REGSET_NUMERIC]; + unsigned int reg_idx = var->reg_reservation.reg_index; + unsigned int i; - if (reg_size == 0) - continue; + assert(reg_size % 4 == 0); + for (i = 0; i < reg_size / 4; ++i) + { + if (get_available_writemask(&allocator, 1, UINT_MAX, reg_idx + i) != VKD3DSP_WRITEMASK_ALL) + { + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, + "Overlapping register() reservations on 'c%u'.", reg_idx + i); + } + + record_allocation(ctx, &allocator, reg_idx + i, VKD3DSP_WRITEMASK_ALL, 1, UINT_MAX); + } + + var->regs[HLSL_REGSET_NUMERIC].id = reg_idx; + var->regs[HLSL_REGSET_NUMERIC].allocation_size = reg_size / 4; + var->regs[HLSL_REGSET_NUMERIC].writemask = VKD3DSP_WRITEMASK_ALL; + var->regs[HLSL_REGSET_NUMERIC].allocated = true; + TRACE("Allocated reserved %s to %s.\n", var->name, + debug_register('c', var->regs[HLSL_REGSET_NUMERIC], var->data_type)); + } + } + + LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) + { + unsigned int reg_size = var->data_type->reg_size[HLSL_REGSET_NUMERIC]; + if (!var->is_uniform || !var->last_read || reg_size == 0) + continue; + + if (!var->regs[HLSL_REGSET_NUMERIC].allocated) + { var->regs[HLSL_REGSET_NUMERIC] = allocate_numeric_registers_for_type(ctx, &allocator, 1, UINT_MAX, var->data_type); TRACE("Allocated %s to %s.\n", var->name, @@ -4269,45 +4302,52 @@ static const struct hlsl_buffer *get_reserved_buffer(struct hlsl_ctx *ctx, uint3 return NULL; } -static void calculate_buffer_offset(struct hlsl_ctx *ctx, struct hlsl_ir_var *var) +static void calculate_buffer_offset(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, bool register_reservation) { unsigned int var_reg_size = var->data_type->reg_size[HLSL_REGSET_NUMERIC]; enum hlsl_type_class var_class = var->data_type->class; struct hlsl_buffer *buffer = var->buffer; - if (var->reg_reservation.offset_type == 'c') + if (register_reservation) { - if (var->reg_reservation.offset_index % 4) + var->buffer_offset = 4 * var->reg_reservation.reg_index; + } + else + { + if (var->reg_reservation.offset_type == 'c') { - if (var_class == HLSL_CLASS_MATRIX) + if (var->reg_reservation.offset_index % 4) { - hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, - "packoffset() reservations with matrix types must be aligned with the beginning of a register."); - } - else if (var_class == HLSL_CLASS_ARRAY) - { - hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, - "packoffset() reservations with array types must be aligned with the beginning of a register."); - } - else if (var_class == HLSL_CLASS_STRUCT) - { - hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, - "packoffset() reservations with struct types must be aligned with the beginning of a register."); - } - else if (var_class == HLSL_CLASS_VECTOR) - { - unsigned int aligned_offset = hlsl_type_get_sm4_offset(var->data_type, var->reg_reservation.offset_index); - - if (var->reg_reservation.offset_index != aligned_offset) + if (var_class == HLSL_CLASS_MATRIX) + { + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, + "packoffset() reservations with matrix types must be aligned with the beginning of a register."); + } + else if (var_class == HLSL_CLASS_ARRAY) + { + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, + "packoffset() reservations with array types must be aligned with the beginning of a register."); + } + else if (var_class == HLSL_CLASS_STRUCT) + { hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, - "packoffset() reservations with vector types cannot span multiple registers."); + "packoffset() reservations with struct types must be aligned with the beginning of a register."); + } + else if (var_class == HLSL_CLASS_VECTOR) + { + unsigned int aligned_offset = hlsl_type_get_sm4_offset(var->data_type, var->reg_reservation.offset_index); + + if (var->reg_reservation.offset_index != aligned_offset) + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, + "packoffset() reservations with vector types cannot span multiple registers."); + } } + var->buffer_offset = var->reg_reservation.offset_index; + } + else + { + var->buffer_offset = hlsl_type_get_sm4_offset(var->data_type, buffer->size); } - var->buffer_offset = var->reg_reservation.offset_index; - } - else - { - var->buffer_offset = hlsl_type_get_sm4_offset(var->data_type, buffer->size); } TRACE("Allocated buffer offset %u to %s.\n", var->buffer_offset, var->name); @@ -4376,6 +4416,11 @@ static void validate_buffer_offsets(struct hlsl_ctx *ctx) } } +static bool var_has_buffer_offset_register_reservation(struct hlsl_ctx *ctx, const struct hlsl_ir_var *var) +{ + return var->reg_reservation.reg_type == 'c' && var->buffer == ctx->globals_buffer; +} + static void allocate_buffers(struct hlsl_ctx *ctx) { struct hlsl_buffer *buffer; @@ -4384,13 +4429,29 @@ static void allocate_buffers(struct hlsl_ctx *ctx) LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { - if (var->is_uniform && !hlsl_type_is_resource(var->data_type)) - { - if (var->is_param) - var->buffer = ctx->params_buffer; + if (!var->is_uniform || hlsl_type_is_resource(var->data_type)) + continue; - calculate_buffer_offset(ctx, var); - } + if (var->is_param) + var->buffer = ctx->params_buffer; + } + + LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) + { + if (!var->is_uniform || hlsl_type_is_resource(var->data_type)) + continue; + + if (var_has_buffer_offset_register_reservation(ctx, var)) + calculate_buffer_offset(ctx, var, true); + } + + LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) + { + if (!var->is_uniform || hlsl_type_is_resource(var->data_type)) + continue; + + if (!var_has_buffer_offset_register_reservation(ctx, var)) + calculate_buffer_offset(ctx, var, false); } validate_buffer_offsets(ctx); diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c index 9079be48b4f..a0d6212cbf5 100644 --- a/libs/vkd3d/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d/libs/vkd3d-shader/ir.c @@ -66,7 +66,7 @@ static void remove_dcl_temps(struct vsir_program *program) } } -static bool vsir_instruction_init_with_params(struct vkd3d_shader_parser *parser, +static bool vsir_instruction_init_with_params(struct vsir_program *program, struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, enum vkd3d_shader_opcode handler_idx, unsigned int dst_count, unsigned int src_count) { @@ -74,13 +74,13 @@ static bool vsir_instruction_init_with_params(struct vkd3d_shader_parser *parser ins->dst_count = dst_count; ins->src_count = src_count; - if (!(ins->dst = shader_parser_get_dst_params(parser, ins->dst_count))) + if (!(ins->dst = vsir_program_get_dst_params(program, ins->dst_count))) { ERR("Failed to allocate %u destination parameters.\n", dst_count); return false; } - if (!(ins->src = shader_parser_get_src_params(parser, ins->src_count))) + if (!(ins->src = vsir_program_get_src_params(program, ins->src_count))) { ERR("Failed to allocate %u source parameters.\n", src_count); return false; @@ -116,7 +116,7 @@ static enum vkd3d_result instruction_array_lower_texkills(struct vkd3d_shader_pa /* tmp = ins->dst[0] < 0 */ ins = &instructions->elements[i + 1]; - if (!vsir_instruction_init_with_params(parser, ins, &texkill_ins->location, VKD3DSIH_LTO, 1, 2)) + if (!vsir_instruction_init_with_params(program, ins, &texkill_ins->location, VKD3DSIH_LTO, 1, 2)) return VKD3D_ERROR_OUT_OF_MEMORY; vsir_register_init(&ins->dst[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); @@ -139,7 +139,7 @@ static enum vkd3d_result instruction_array_lower_texkills(struct vkd3d_shader_pa for (k = 1; k < components_read; ++k) { ins = &instructions->elements[i + 1 + k]; - if (!(vsir_instruction_init_with_params(parser, ins, &texkill_ins->location, VKD3DSIH_OR, 1, 2))) + if (!(vsir_instruction_init_with_params(program, ins, &texkill_ins->location, VKD3DSIH_OR, 1, 2))) return VKD3D_ERROR_OUT_OF_MEMORY; vsir_register_init(&ins->dst[0].reg, VKD3DSPR_TEMP, VKD3D_DATA_UINT, 1); @@ -160,7 +160,7 @@ static enum vkd3d_result instruction_array_lower_texkills(struct vkd3d_shader_pa /* discard_nz tmp.x */ ins = &instructions->elements[i + 1 + components_read]; - if (!(vsir_instruction_init_with_params(parser, ins, &texkill_ins->location, VKD3DSIH_DISCARD, 0, 1))) + if (!(vsir_instruction_init_with_params(program, ins, &texkill_ins->location, VKD3DSIH_DISCARD, 0, 1))) return VKD3D_ERROR_OUT_OF_MEMORY; ins->flags = VKD3D_SHADER_CONDITIONAL_OP_NZ; @@ -442,6 +442,15 @@ void vsir_src_param_init(struct vkd3d_shader_src_param *param, enum vkd3d_shader param->modifiers = VKD3DSPSM_NONE; } +void vsir_dst_param_init(struct vkd3d_shader_dst_param *param, enum vkd3d_shader_register_type reg_type, + enum vkd3d_data_type data_type, unsigned int idx_count) +{ + vsir_register_init(¶m->reg, reg_type, data_type, idx_count); + param->write_mask = VKD3DSP_WRITEMASK_0; + param->modifiers = VKD3DSPDM_NONE; + param->shift = 0; +} + void vsir_src_param_init_label(struct vkd3d_shader_src_param *param, unsigned int label_id) { vsir_src_param_init(param, VKD3DSPR_LABEL, VKD3D_DATA_UINT, 1); @@ -449,6 +458,18 @@ void vsir_src_param_init_label(struct vkd3d_shader_src_param *param, unsigned in param->reg.idx[0].offset = label_id; } +static void src_param_init_ssa_bool(struct vkd3d_shader_src_param *src, unsigned int idx) +{ + vsir_src_param_init(src, VKD3DSPR_SSA, VKD3D_DATA_BOOL, 1); + src->reg.idx[0].offset = idx; +} + +static void dst_param_init_ssa_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx) +{ + vsir_dst_param_init(dst, VKD3DSPR_SSA, VKD3D_DATA_BOOL, 1); + dst->reg.idx[0].offset = idx; +} + void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, enum vkd3d_shader_opcode handler_idx) { @@ -457,12 +478,12 @@ void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vk ins->handler_idx = handler_idx; } -static bool vsir_instruction_init_label(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, - unsigned int label_id, void *parser) +static bool vsir_instruction_init_label(struct vkd3d_shader_instruction *ins, + const struct vkd3d_shader_location *location, unsigned int label_id, struct vsir_program *program) { struct vkd3d_shader_src_param *src_param; - if (!(src_param = shader_parser_get_src_params(parser, 1))) + if (!(src_param = vsir_program_get_src_params(program, 1))) return false; vsir_src_param_init_label(src_param, label_id); @@ -1808,8 +1829,9 @@ static unsigned int cf_flattener_alloc_block_id(struct cf_flattener *flattener) static struct vkd3d_shader_src_param *instruction_src_params_alloc(struct vkd3d_shader_instruction *ins, unsigned int count, struct cf_flattener *flattener) { - struct vkd3d_shader_src_param *params = shader_parser_get_src_params(flattener->parser, count); - if (!params) + struct vkd3d_shader_src_param *params; + + if (!(params = vsir_program_get_src_params(&flattener->parser->program, count))) { flattener->allocation_failed = true; return NULL; @@ -1825,7 +1847,7 @@ static void cf_flattener_emit_label(struct cf_flattener *flattener, unsigned int if (!(ins = cf_flattener_require_space(flattener, 1))) return; - if (vsir_instruction_init_label(ins, &flattener->location, label_id, flattener->parser)) + if (vsir_instruction_init_label(ins, &flattener->location, label_id, &flattener->parser->program)) ++flattener->instruction_count; else flattener->allocation_failed = true; @@ -2350,6 +2372,271 @@ static enum vkd3d_result flatten_control_flow_constructs(struct vkd3d_shader_par return result; } +static unsigned int label_from_src_param(const struct vkd3d_shader_src_param *param) +{ + assert(param->reg.type == VKD3DSPR_LABEL); + return param->reg.idx[0].offset; +} + +static bool reserve_instructions(struct vkd3d_shader_instruction **instructions, size_t *capacity, size_t count) +{ + if (!vkd3d_array_reserve((void **)instructions, capacity, count, sizeof(**instructions))) + { + ERR("Failed to allocate instructions.\n"); + return false; + } + + return true; +} + +/* A record represents replacing a jump from block `switch_label' to + * block `target_label' with a jump from block `if_label' to block + * `target_label'. */ +struct lower_switch_to_if_ladder_block_mapping +{ + unsigned int switch_label; + unsigned int if_label; + unsigned int target_label; +}; + +static bool lower_switch_to_if_ladder_add_block_mapping(struct lower_switch_to_if_ladder_block_mapping **block_map, + size_t *map_capacity, size_t *map_count, unsigned int switch_label, unsigned int if_label, unsigned int target_label) +{ + if (!vkd3d_array_reserve((void **)block_map, map_capacity, *map_count + 1, sizeof(**block_map))) + { + ERR("Failed to allocate block mapping.\n"); + return false; + } + + (*block_map)[*map_count].switch_label = switch_label; + (*block_map)[*map_count].if_label = if_label; + (*block_map)[*map_count].target_label = target_label; + + *map_count += 1; + + return true; +} + +static enum vkd3d_result lower_switch_to_if_ladder(struct vsir_program *program) +{ + unsigned int block_count = program->block_count, ssa_count = program->ssa_count, current_label = 0, if_label; + size_t ins_capacity = 0, ins_count = 0, i, map_capacity = 0, map_count = 0; + struct vkd3d_shader_instruction *instructions = NULL; + struct lower_switch_to_if_ladder_block_mapping *block_map = NULL; + + if (!reserve_instructions(&instructions, &ins_capacity, program->instructions.count)) + goto fail; + + /* First subpass: convert SWITCH_MONOLITHIC instructions to + * selection ladders, keeping a map between blocks before and + * after the subpass. */ + for (i = 0; i < program->instructions.count; ++i) + { + struct vkd3d_shader_instruction *ins = &program->instructions.elements[i]; + unsigned int case_count, j, default_label; + + switch (ins->handler_idx) + { + case VKD3DSIH_LABEL: + current_label = label_from_src_param(&ins->src[0]); + if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1)) + goto fail; + instructions[ins_count++] = *ins; + continue; + + case VKD3DSIH_SWITCH_MONOLITHIC: + break; + + default: + if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1)) + goto fail; + instructions[ins_count++] = *ins; + continue; + } + + case_count = (ins->src_count - 3) / 2; + default_label = label_from_src_param(&ins->src[1]); + + /* In principle we can have a switch with no cases, and we + * just have to jump to the default label. */ + if (case_count == 0) + { + if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1)) + goto fail; + + if (!vsir_instruction_init_with_params(program, &instructions[ins_count], + &ins->location, VKD3DSIH_BRANCH, 0, 1)) + goto fail; + vsir_src_param_init_label(&instructions[ins_count].src[0], default_label); + ++ins_count; + } + + if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 3 * case_count - 1)) + goto fail; + + if_label = current_label; + + for (j = 0; j < case_count; ++j) + { + unsigned int fallthrough_label, case_label = label_from_src_param(&ins->src[3 + 2 * j + 1]); + + if (!vsir_instruction_init_with_params(program, + &instructions[ins_count], &ins->location, VKD3DSIH_IEQ, 1, 2)) + goto fail; + dst_param_init_ssa_bool(&instructions[ins_count].dst[0], ssa_count); + instructions[ins_count].src[0] = ins->src[0]; + instructions[ins_count].src[1] = ins->src[3 + 2 * j]; + ++ins_count; + + /* For all cases except the last one we fall through to + * the following case; the last one has to jump to the + * default label. */ + if (j == case_count - 1) + fallthrough_label = default_label; + else + fallthrough_label = block_count + 1; + + if (!vsir_instruction_init_with_params(program, &instructions[ins_count], + &ins->location, VKD3DSIH_BRANCH, 0, 3)) + goto fail; + src_param_init_ssa_bool(&instructions[ins_count].src[0], ssa_count); + vsir_src_param_init_label(&instructions[ins_count].src[1], case_label); + vsir_src_param_init_label(&instructions[ins_count].src[2], fallthrough_label); + ++ins_count; + + ++ssa_count; + + if (!lower_switch_to_if_ladder_add_block_mapping(&block_map, &map_capacity, &map_count, + current_label, if_label, case_label)) + goto fail; + + if (j == case_count - 1) + { + if (!lower_switch_to_if_ladder_add_block_mapping(&block_map, &map_capacity, &map_count, + current_label, if_label, default_label)) + goto fail; + } + else + { + if (!vsir_instruction_init_with_params(program, + &instructions[ins_count], &ins->location, VKD3DSIH_LABEL, 0, 1)) + goto fail; + vsir_src_param_init_label(&instructions[ins_count].src[0], ++block_count); + ++ins_count; + + if_label = block_count; + } + } + } + + /* Second subpass: creating new blocks might have broken + * references in PHI instructions, so we use the block map to fix + * them. */ + current_label = 0; + for (i = 0; i < ins_count; ++i) + { + struct vkd3d_shader_instruction *ins = &instructions[i]; + struct vkd3d_shader_src_param *new_src; + unsigned int j, l, new_src_count = 0; + + switch (ins->handler_idx) + { + case VKD3DSIH_LABEL: + current_label = label_from_src_param(&ins->src[0]); + continue; + + case VKD3DSIH_PHI: + break; + + default: + continue; + } + + /* First count how many source parameters we need. */ + for (j = 0; j < ins->src_count; j += 2) + { + unsigned int source_label = label_from_src_param(&ins->src[j + 1]); + size_t k, match_count = 0; + + for (k = 0; k < map_count; ++k) + { + struct lower_switch_to_if_ladder_block_mapping *mapping = &block_map[k]; + + if (mapping->switch_label == source_label && mapping->target_label == current_label) + match_count += 1; + } + + new_src_count += (match_count != 0) ? 2 * match_count : 2; + } + + assert(new_src_count >= ins->src_count); + + /* Allocate more source parameters if needed. */ + if (new_src_count == ins->src_count) + { + new_src = ins->src; + } + else + { + if (!(new_src = vsir_program_get_src_params(program, new_src_count))) + { + ERR("Failed to allocate %u source parameters.\n", new_src_count); + goto fail; + } + } + + /* Then do the copy. */ + for (j = 0, l = 0; j < ins->src_count; j += 2) + { + unsigned int source_label = label_from_src_param(&ins->src[j + 1]); + size_t k, match_count = 0; + + for (k = 0; k < map_count; ++k) + { + struct lower_switch_to_if_ladder_block_mapping *mapping = &block_map[k]; + + if (mapping->switch_label == source_label && mapping->target_label == current_label) + { + match_count += 1; + + new_src[l] = ins->src[j]; + new_src[l + 1] = ins->src[j + 1]; + new_src[l + 1].reg.idx[0].offset = mapping->if_label; + l += 2; + } + } + + if (match_count == 0) + { + new_src[l] = ins->src[j]; + new_src[l + 1] = ins->src[j + 1]; + l += 2; + } + } + + assert(l == new_src_count); + + ins->src_count = new_src_count; + ins->src = new_src; + } + + vkd3d_free(program->instructions.elements); + vkd3d_free(block_map); + program->instructions.elements = instructions; + program->instructions.capacity = ins_capacity; + program->instructions.count = ins_count; + program->block_count = block_count; + program->ssa_count = ssa_count; + + return VKD3D_OK; + +fail: + vkd3d_free(instructions); + vkd3d_free(block_map); + + return VKD3D_ERROR_OUT_OF_MEMORY; +} + enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, const struct vkd3d_shader_compile_info *compile_info) { @@ -2361,7 +2648,12 @@ enum vkd3d_result vkd3d_shader_normalise(struct vkd3d_shader_parser *parser, if ((result = instruction_array_lower_texkills(parser)) < 0) return result; - if (!parser->shader_desc.is_dxil) + if (parser->shader_desc.is_dxil) + { + if ((result = lower_switch_to_if_ladder(&parser->program)) < 0) + return result; + } + else { if (parser->program.shader_version.type != VKD3D_SHADER_TYPE_PIXEL) { @@ -2431,6 +2723,7 @@ struct validation_context struct validation_context_ssa_data { enum vsir_dimension dimension; + enum vkd3d_data_type data_type; size_t first_seen; uint32_t write_mask; uint32_t read_mask; @@ -2587,13 +2880,20 @@ static void vsir_validate_register(struct validation_context *ctx, if (data->dimension == VSIR_DIMENSION_NONE) { data->dimension = reg->dimension; + data->data_type = reg->data_type; data->first_seen = ctx->instruction_idx; } - else if (data->dimension != reg->dimension) + else { - validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension %#x for a SSA register: " - "it has already been seen with dimension %#x at instruction %zu.", - reg->dimension, data->dimension, data->first_seen); + if (data->dimension != reg->dimension) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension %#x for a SSA register: " + "it has already been seen with dimension %#x at instruction %zu.", + reg->dimension, data->dimension, data->first_seen); + + if (data_type_is_64_bit(data->data_type) != data_type_is_64_bit(reg->data_type)) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, "Invalid data type %#x for a SSA register: " + "it has already been seen with data type %#x at instruction %zu.", + reg->data_type, data->data_type, data->first_seen); } break; } diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c index a86ca583e63..aedbfc24a93 100644 --- a/libs/vkd3d/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c @@ -3594,11 +3594,17 @@ static bool vkd3d_swizzle_is_equal(uint32_t dst_write_mask, uint32_t swizzle, ui return vkd3d_compact_swizzle(VKD3D_SHADER_NO_SWIZZLE, dst_write_mask) == vkd3d_compact_swizzle(swizzle, write_mask); } -static bool vkd3d_swizzle_is_scalar(uint32_t swizzle) +static bool vkd3d_swizzle_is_scalar(uint32_t swizzle, const struct vkd3d_shader_register *reg) { unsigned int component_idx = vsir_swizzle_get_component(swizzle, 0); - return vsir_swizzle_get_component(swizzle, 1) == component_idx - && vsir_swizzle_get_component(swizzle, 2) == component_idx + + if (vsir_swizzle_get_component(swizzle, 1) != component_idx) + return false; + + if (data_type_is_64_bit(reg->data_type)) + return true; + + return vsir_swizzle_get_component(swizzle, 2) == component_idx && vsir_swizzle_get_component(swizzle, 3) == component_idx; } @@ -3719,7 +3725,7 @@ static uint32_t spirv_compiler_emit_load_constant64(struct spirv_compiler *compi for (i = 0, j = 0; i < VKD3D_DVEC2_SIZE; ++i) { if (write_mask & (VKD3DSP_WRITEMASK_0 << i)) - values[j++] = reg->u.immconst_u64[vsir_swizzle_get_component64(swizzle, i)]; + values[j++] = reg->u.immconst_u64[vsir_swizzle_get_component(swizzle, i)]; } } @@ -3886,7 +3892,7 @@ static uint32_t spirv_compiler_emit_load_ssa_reg(struct spirv_compiler *compiler assert(compiler->failed); return 0; } - assert(vkd3d_swizzle_is_scalar(swizzle)); + assert(vkd3d_swizzle_is_scalar(swizzle, reg)); if (reg->dimension == VSIR_DIMENSION_SCALAR) { @@ -3954,6 +3960,7 @@ static uint32_t spirv_compiler_emit_load_reg(struct spirv_compiler *compiler, val_id = vkd3d_spirv_build_op_load(builder, type_id, reg_info.id, SpvMemoryAccessMaskNone); } + swizzle = data_type_is_64_bit(reg->data_type) ? vsir_swizzle_32_from_64(swizzle) : swizzle; val_id = spirv_compiler_emit_swizzle(compiler, val_id, reg_info.write_mask, reg_info.component_type, swizzle, write_mask32); @@ -7047,11 +7054,11 @@ static void spirv_compiler_emit_ext_glsl_instruction(struct spirv_compiler *comp static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { + uint32_t val_id, dst_val_id, type_id, dst_id, src_id, write_mask32, swizzle32; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; struct vkd3d_shader_register_info dst_reg_info, src_reg_info; const struct vkd3d_shader_dst_param *dst = instruction->dst; const struct vkd3d_shader_src_param *src = instruction->src; - uint32_t val_id, dst_val_id, type_id, dst_id, src_id; uint32_t components[VKD3D_VEC4_SIZE]; unsigned int i, component_count; @@ -7075,7 +7082,9 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, return; } - component_count = vsir_write_mask_component_count(dst->write_mask); + write_mask32 = data_type_is_64_bit(dst->reg.data_type) ? vsir_write_mask_32_from_64(dst->write_mask) : dst->write_mask; + swizzle32 = data_type_is_64_bit(dst->reg.data_type) ? vsir_swizzle_32_from_64(src->swizzle) : src->swizzle; + component_count = vsir_write_mask_component_count(write_mask32); if (component_count != 1 && component_count != VKD3D_VEC4_SIZE && dst_reg_info.write_mask == VKD3DSP_WRITEMASK_ALL) { @@ -7088,8 +7097,8 @@ static void spirv_compiler_emit_mov(struct spirv_compiler *compiler, for (i = 0; i < ARRAY_SIZE(components); ++i) { - if (dst->write_mask & (VKD3DSP_WRITEMASK_0 << i)) - components[i] = VKD3D_VEC4_SIZE + vsir_swizzle_get_component(src->swizzle, i); + if (write_mask32 & (VKD3DSP_WRITEMASK_0 << i)) + components[i] = VKD3D_VEC4_SIZE + vsir_swizzle_get_component(swizzle32, i); else components[i] = i; } @@ -7472,7 +7481,7 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp const struct vkd3d_shader_dst_param *dst = instruction->dst; const struct vkd3d_shader_src_param *src = instruction->src; enum vkd3d_shader_component_type component_type; - unsigned int i, j, k, src_count; + unsigned int i, j, k, src_count, size; uint32_t write_mask; SpvOp op; @@ -7481,8 +7490,9 @@ static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *comp component_type = vkd3d_component_type_from_data_type(dst->reg.data_type); type_id = vkd3d_spirv_get_type_id(builder, component_type, 1); - mask_id = spirv_compiler_get_constant_uint(compiler, 0x1f); - size_id = spirv_compiler_get_constant_uint(compiler, 0x20); + size = (src[src_count - 1].reg.data_type == VKD3D_DATA_UINT64) ? 0x40 : 0x20; + mask_id = spirv_compiler_get_constant_uint(compiler, size - 1); + size_id = spirv_compiler_get_constant_uint(compiler, size); switch (instruction->handler_idx) { @@ -7813,13 +7823,16 @@ static void spirv_compiler_emit_branch(struct spirv_compiler *compiler, if (instruction->src_count > 1) { /* Loop merge only. Must have a merge block and a continue block. */ - spirv_compiler_emit_merge(compiler, src[1].reg.idx[0].offset, src[2].reg.idx[0].offset); + if (instruction->src_count == 3) + spirv_compiler_emit_merge(compiler, src[1].reg.idx[0].offset, src[2].reg.idx[0].offset); + else + ERR("Invalid branch with %u sources.\n", instruction->src_count); } vkd3d_spirv_build_op_branch(builder, spirv_compiler_get_label_id(compiler, src[0].reg.idx[0].offset)); return; } - if (!vkd3d_swizzle_is_scalar(src->swizzle)) + if (!vkd3d_swizzle_is_scalar(src->swizzle, &src->reg)) { WARN("Unexpected src swizzle %#x.\n", src->swizzle); spirv_compiler_warning(compiler, VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE, @@ -7827,11 +7840,15 @@ static void spirv_compiler_emit_branch(struct spirv_compiler *compiler, } condition_id = spirv_compiler_emit_load_src(compiler, &src[0], VKD3DSP_WRITEMASK_0); - condition_id = spirv_compiler_emit_int_to_bool(compiler, - VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, 1, condition_id); + if (src[0].reg.data_type != VKD3D_DATA_BOOL) + condition_id = spirv_compiler_emit_int_to_bool(compiler, + VKD3D_SHADER_CONDITIONAL_OP_NZ, src[0].reg.data_type, 1, condition_id); /* Emit the merge immediately before the branch instruction. */ - spirv_compiler_emit_merge(compiler, src[3].reg.idx[0].offset, - (instruction->src_count > 4) ? src[4].reg.idx[0].offset : 0); + if (instruction->src_count >= 4) + spirv_compiler_emit_merge(compiler, src[3].reg.idx[0].offset, + (instruction->src_count > 4) ? src[4].reg.idx[0].offset : 0); + else + ERR("Invalid branch with %u sources.\n", instruction->src_count); vkd3d_spirv_build_op_branch_conditional(builder, condition_id, spirv_compiler_get_label_id(compiler, src[1].reg.idx[0].offset), spirv_compiler_get_label_id(compiler, src[2].reg.idx[0].offset)); @@ -7846,7 +7863,7 @@ static void spirv_compiler_emit_switch(struct spirv_compiler *compiler, unsigned int i, word_count; uint32_t *cases; - if (!vkd3d_swizzle_is_scalar(src[0].swizzle)) + if (!vkd3d_swizzle_is_scalar(src[0].swizzle, &src[0].reg)) { WARN("Unexpected src swizzle %#x.\n", src[0].swizzle); spirv_compiler_warning(compiler, VKD3D_SHADER_WARNING_SPV_INVALID_SWIZZLE, @@ -9964,6 +9981,7 @@ static int spirv_compiler_generate_spirv(struct spirv_compiler *compiler, enum vkd3d_shader_spirv_environment environment = spirv_compiler_get_target_environment(compiler); if (vkd3d_spirv_binary_to_text(spirv, environment, compiler->formatting, &text) != VKD3D_OK) return VKD3D_ERROR; + vkd3d_shader_free_shader_code(spirv); *spirv = text; } diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c index 50146c2c7c9..adfddd32036 100644 --- a/libs/vkd3d/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c @@ -1742,7 +1742,7 @@ static bool shader_sm4_read_reg_idx(struct vkd3d_shader_sm4_parser *priv, const { if (addressing & VKD3D_SM4_ADDRESSING_RELATIVE) { - struct vkd3d_shader_src_param *rel_addr = shader_parser_get_src_params(&priv->p, 1); + struct vkd3d_shader_src_param *rel_addr = vsir_program_get_src_params(&priv->p.program, 1); if (!(reg_idx->rel_addr = rel_addr)) { @@ -2161,6 +2161,9 @@ static bool shader_sm4_read_src_param(struct vkd3d_shader_sm4_parser *priv, cons break; } + if (data_type_is_64_bit(data_type)) + src_param->swizzle = vsir_swizzle_64_from_32(src_param->swizzle); + if (register_is_input_output(&src_param->reg) && !shader_sm4_validate_input_output_register(priv, &src_param->reg, mask_from_swizzle(src_param->swizzle))) return false; @@ -2341,6 +2344,7 @@ static void shader_sm4_read_instruction_modifier(uint32_t modifier, struct vkd3d static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, struct vkd3d_shader_instruction *ins) { const struct vkd3d_sm4_opcode_info *opcode_info; + struct vsir_program *program = &sm4->p.program; uint32_t opcode_token, opcode, previous_token; struct vkd3d_shader_dst_param *dst_params; struct vkd3d_shader_src_param *src_params; @@ -2399,7 +2403,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str ins->predicate = NULL; ins->dst_count = strnlen(opcode_info->dst_info, SM4_MAX_DST_COUNT); ins->src_count = strnlen(opcode_info->src_info, SM4_MAX_SRC_COUNT); - ins->src = src_params = shader_parser_get_src_params(&sm4->p, ins->src_count); + ins->src = src_params = vsir_program_get_src_params(program, ins->src_count); if (!src_params && ins->src_count) { ERR("Failed to allocate src parameters.\n"); @@ -2441,7 +2445,7 @@ static void shader_sm4_read_instruction(struct vkd3d_shader_sm4_parser *sm4, str precise = (opcode_token & VKD3D_SM5_PRECISE_MASK) >> VKD3D_SM5_PRECISE_SHIFT; ins->flags |= precise << VKD3DSI_PRECISE_SHIFT; - ins->dst = dst_params = shader_parser_get_dst_params(&sm4->p, ins->dst_count); + ins->dst = dst_params = vsir_program_get_dst_params(program, ins->dst_count); if (!dst_params && ins->dst_count) { ERR("Failed to allocate dst parameters.\n"); diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c index 1b7ea8dde9a..d0fd6b047b1 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c @@ -424,12 +424,12 @@ void set_string(struct vkd3d_bytecode_buffer *buffer, size_t offset, const char static void vkd3d_shader_dump_blob(const char *path, const char *profile, const char *suffix, const void *data, size_t size) { - static LONG shader_id = 0; + static unsigned int shader_id = 0; char filename[1024]; unsigned int id; FILE *f; - id = InterlockedIncrement(&shader_id) - 1; + id = vkd3d_atomic_increment_u32(&shader_id) - 1; if (profile) snprintf(filename, ARRAY_SIZE(filename), "%s/vkd3d-shader-%u-%s.%s", path, id, profile, suffix); diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h index fd0f2f0f34a..0ba7e71922a 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h @@ -895,6 +895,8 @@ struct vkd3d_shader_src_param void vsir_src_param_init(struct vkd3d_shader_src_param *param, enum vkd3d_shader_register_type reg_type, enum vkd3d_data_type data_type, unsigned int idx_count); +void vsir_dst_param_init(struct vkd3d_shader_dst_param *param, enum vkd3d_shader_register_type reg_type, + enum vkd3d_data_type data_type, unsigned int idx_count); void vsir_src_param_init_label(struct vkd3d_shader_src_param *param, unsigned int label_id); struct vkd3d_shader_index_range @@ -1285,6 +1287,18 @@ struct vsir_program 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); +static inline struct vkd3d_shader_dst_param *vsir_program_get_dst_params( + struct vsir_program *program, unsigned int count) +{ + return shader_dst_param_allocator_get(&program->instructions.dst_params, count); +} + +static inline struct vkd3d_shader_src_param *vsir_program_get_src_params( + struct vsir_program *program, unsigned int count) +{ + return shader_src_param_allocator_get(&program->instructions.src_params, count); +} + struct vkd3d_shader_parser { struct vkd3d_shader_message_context *message_context; @@ -1312,18 +1326,6 @@ bool vkd3d_shader_parser_init(struct vkd3d_shader_parser *parser, void vkd3d_shader_parser_warning(struct vkd3d_shader_parser *parser, enum vkd3d_shader_error error, const char *format, ...) VKD3D_PRINTF_FUNC(3, 4); -static inline struct vkd3d_shader_dst_param *shader_parser_get_dst_params( - struct vkd3d_shader_parser *parser, unsigned int count) -{ - return shader_dst_param_allocator_get(&parser->program.instructions.dst_params, count); -} - -static inline struct vkd3d_shader_src_param *shader_parser_get_src_params( - struct vkd3d_shader_parser *parser, unsigned int count) -{ - return shader_src_param_allocator_get(&parser->program.instructions.src_params, count); -} - static inline void vkd3d_shader_parser_destroy(struct vkd3d_shader_parser *parser) { parser->ops->parser_destroy(parser); @@ -1603,25 +1605,89 @@ static inline unsigned int vkd3d_write_mask_from_component_count(unsigned int co static inline uint32_t vsir_write_mask_64_from_32(uint32_t write_mask32) { - uint32_t write_mask64 = write_mask32 | (write_mask32 >> 1); - return (write_mask64 & VKD3DSP_WRITEMASK_0) | ((write_mask64 & VKD3DSP_WRITEMASK_2) >> 1); + switch (write_mask32) + { + case VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1: + return VKD3DSP_WRITEMASK_0; + + case VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3: + return VKD3DSP_WRITEMASK_1; + + case VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1 | VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3: + return VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1; + + default: + ERR("Invalid 32 bit writemask when converting to 64 bit: %#x.\n", write_mask32); + return VKD3DSP_WRITEMASK_0; + } } static inline uint32_t vsir_write_mask_32_from_64(uint32_t write_mask64) { - uint32_t write_mask32 = (write_mask64 | (write_mask64 << 1)) - & (VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_2); - return write_mask32 | (write_mask32 << 1); + switch (write_mask64) + { + case VKD3DSP_WRITEMASK_0: + return VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1; + + case VKD3DSP_WRITEMASK_1: + return VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3; + + case VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1: + return VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1 | VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3; + + default: + ERR("Invalid 64 bit writemask: %#x.\n", write_mask64); + return VKD3DSP_WRITEMASK_0; + } +} + +static inline uint32_t vsir_swizzle_64_from_32(uint32_t swizzle32) +{ + switch (swizzle32) + { + case VKD3D_SHADER_SWIZZLE(X, Y, X, Y): + return VKD3D_SHADER_SWIZZLE(X, X, X, X); + + case VKD3D_SHADER_SWIZZLE(X, Y, Z, W): + return VKD3D_SHADER_SWIZZLE(X, Y, X, X); + + case VKD3D_SHADER_SWIZZLE(Z, W, X, Y): + return VKD3D_SHADER_SWIZZLE(Y, X, X, X); + + case VKD3D_SHADER_SWIZZLE(Z, W, Z, W): + return VKD3D_SHADER_SWIZZLE(Y, Y, X, X); + + default: + ERR("Invalid 32 bit swizzle when converting to 64 bit: %#x.\n", swizzle32); + return VKD3D_SHADER_SWIZZLE(X, X, X, X); + } } -static inline unsigned int vsir_swizzle_get_component(uint32_t swizzle, unsigned int idx) +static inline uint32_t vsir_swizzle_32_from_64(uint32_t swizzle64) { - return (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(idx)) & VKD3D_SHADER_SWIZZLE_MASK; + switch (swizzle64) + { + case VKD3D_SHADER_SWIZZLE(X, X, X, X): + return VKD3D_SHADER_SWIZZLE(X, Y, X, Y); + + case VKD3D_SHADER_SWIZZLE(X, Y, X, X): + return VKD3D_SHADER_SWIZZLE(X, Y, Z, W); + + case VKD3D_SHADER_SWIZZLE(Y, X, X, X): + return VKD3D_SHADER_SWIZZLE(Z, W, X, Y); + + case VKD3D_SHADER_SWIZZLE(Y, Y, X, X): + return VKD3D_SHADER_SWIZZLE(Z, W, Z, W); + + default: + ERR("Invalid 64 bit swizzle: %#x.\n", swizzle64); + return VKD3D_SHADER_SWIZZLE(X, Y, X, Y); + } } -static inline unsigned int vsir_swizzle_get_component64(uint32_t swizzle, unsigned int idx) +static inline unsigned int vsir_swizzle_get_component(uint32_t swizzle, unsigned int idx) { - return ((swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(idx * 2)) & VKD3D_SHADER_SWIZZLE_MASK) / 2u; + return (swizzle >> VKD3D_SHADER_SWIZZLE_SHIFT(idx)) & VKD3D_SHADER_SWIZZLE_MASK; } static inline unsigned int vkd3d_compact_swizzle(uint32_t swizzle, uint32_t write_mask) diff --git a/libs/vkd3d/libs/vkd3d/device.c b/libs/vkd3d/libs/vkd3d/device.c index 2b8558175e0..e45072b9367 100644 --- a/libs/vkd3d/libs/vkd3d/device.c +++ b/libs/vkd3d/libs/vkd3d/device.c @@ -750,7 +750,7 @@ static void vkd3d_destroy_instance(struct vkd3d_instance *instance) ULONG vkd3d_instance_incref(struct vkd3d_instance *instance) { - ULONG refcount = InterlockedIncrement(&instance->refcount); + unsigned int refcount = vkd3d_atomic_increment_u32(&instance->refcount); TRACE("%p increasing refcount to %u.\n", instance, refcount); @@ -759,7 +759,7 @@ ULONG vkd3d_instance_incref(struct vkd3d_instance *instance) ULONG vkd3d_instance_decref(struct vkd3d_instance *instance) { - ULONG refcount = InterlockedDecrement(&instance->refcount); + unsigned int refcount = vkd3d_atomic_decrement_u32(&instance->refcount); TRACE("%p decreasing refcount to %u.\n", instance, refcount); @@ -2531,7 +2531,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_QueryInterface(ID3D12Device5 *ifac static ULONG STDMETHODCALLTYPE d3d12_device_AddRef(ID3D12Device5 *iface) { struct d3d12_device *device = impl_from_ID3D12Device5(iface); - ULONG refcount = InterlockedIncrement(&device->refcount); + unsigned int refcount = vkd3d_atomic_increment_u32(&device->refcount); TRACE("%p increasing refcount to %u.\n", device, refcount); @@ -2563,7 +2563,7 @@ static HRESULT device_worker_stop(struct d3d12_device *device) static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device5 *iface) { struct d3d12_device *device = impl_from_ID3D12Device5(iface); - ULONG refcount = InterlockedDecrement(&device->refcount); + unsigned int refcount = vkd3d_atomic_decrement_u32(&device->refcount); TRACE("%p decreasing refcount to %u.\n", device, refcount); @@ -4473,8 +4473,8 @@ void d3d12_device_mark_as_removed(struct d3d12_device *device, HRESULT reason, va_list args; va_start(args, message); - WARN("Device %p is lost (reason %#x, \"%s\").\n", - device, reason, vkd3d_dbg_vsprintf(message, args)); + WARN("Device %p is lost (reason %s, \"%s\").\n", + device, debugstr_hresult(reason), vkd3d_dbg_vsprintf(message, args)); va_end(args); device->removed_reason = reason; diff --git a/libs/vkd3d/libs/vkd3d/resource.c b/libs/vkd3d/libs/vkd3d/resource.c index a360b0ef4dd..cd2f9af0e39 100644 --- a/libs/vkd3d/libs/vkd3d/resource.c +++ b/libs/vkd3d/libs/vkd3d/resource.c @@ -308,7 +308,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_heap_QueryInterface(ID3D12Heap *iface, static ULONG STDMETHODCALLTYPE d3d12_heap_AddRef(ID3D12Heap *iface) { struct d3d12_heap *heap = impl_from_ID3D12Heap(iface); - ULONG refcount = InterlockedIncrement(&heap->refcount); + unsigned int refcount = vkd3d_atomic_increment_u32(&heap->refcount); TRACE("%p increasing refcount to %u.\n", heap, refcount); @@ -345,7 +345,7 @@ static void d3d12_heap_destroy(struct d3d12_heap *heap) static ULONG STDMETHODCALLTYPE d3d12_heap_Release(ID3D12Heap *iface) { struct d3d12_heap *heap = impl_from_ID3D12Heap(iface); - ULONG refcount = InterlockedDecrement(&heap->refcount); + unsigned int refcount = vkd3d_atomic_decrement_u32(&heap->refcount); TRACE("%p decreasing refcount to %u.\n", heap, refcount); @@ -358,7 +358,7 @@ static ULONG STDMETHODCALLTYPE d3d12_heap_Release(ID3D12Heap *iface) static void d3d12_heap_resource_destroyed(struct d3d12_heap *heap) { - if (!InterlockedDecrement(&heap->resource_count) && (!heap->refcount || heap->is_private)) + if (!vkd3d_atomic_decrement_u32(&heap->resource_count) && (!heap->refcount || heap->is_private)) d3d12_heap_destroy(heap); } @@ -1003,7 +1003,7 @@ static void d3d12_resource_destroy(struct d3d12_resource *resource, struct d3d12 static ULONG d3d12_resource_incref(struct d3d12_resource *resource) { - ULONG refcount = InterlockedIncrement(&resource->internal_refcount); + unsigned int refcount = vkd3d_atomic_increment_u32(&resource->internal_refcount); TRACE("%p increasing refcount to %u.\n", resource, refcount); @@ -1012,7 +1012,7 @@ static ULONG d3d12_resource_incref(struct d3d12_resource *resource) static ULONG d3d12_resource_decref(struct d3d12_resource *resource) { - ULONG refcount = InterlockedDecrement(&resource->internal_refcount); + unsigned int refcount = vkd3d_atomic_decrement_u32(&resource->internal_refcount); TRACE("%p decreasing refcount to %u.\n", resource, refcount); @@ -1284,7 +1284,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_QueryInterface(ID3D12Resource1 * static ULONG STDMETHODCALLTYPE d3d12_resource_AddRef(ID3D12Resource1 *iface) { struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface); - ULONG refcount = InterlockedIncrement(&resource->refcount); + unsigned int refcount = vkd3d_atomic_increment_u32(&resource->refcount); TRACE("%p increasing refcount to %u.\n", resource, refcount); @@ -1302,7 +1302,7 @@ static ULONG STDMETHODCALLTYPE d3d12_resource_AddRef(ID3D12Resource1 *iface) static ULONG STDMETHODCALLTYPE d3d12_resource_Release(ID3D12Resource1 *iface) { struct d3d12_resource *resource = impl_from_ID3D12Resource1(iface); - ULONG refcount = InterlockedDecrement(&resource->refcount); + unsigned int refcount = vkd3d_atomic_decrement_u32(&resource->refcount); TRACE("%p decreasing refcount to %u.\n", resource, refcount); @@ -2174,7 +2174,7 @@ static HRESULT vkd3d_bind_heap_memory(struct d3d12_device *device, { resource->heap = heap; resource->heap_offset = heap_offset; - InterlockedIncrement(&heap->resource_count); + vkd3d_atomic_increment_u32(&heap->resource_count); } else { @@ -4010,7 +4010,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_descriptor_heap_QueryInterface(ID3D12Desc static ULONG STDMETHODCALLTYPE d3d12_descriptor_heap_AddRef(ID3D12DescriptorHeap *iface) { struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface); - ULONG refcount = InterlockedIncrement(&heap->refcount); + unsigned int refcount = vkd3d_atomic_increment_u32(&heap->refcount); TRACE("%p increasing refcount to %u.\n", heap, refcount); @@ -4020,7 +4020,7 @@ static ULONG STDMETHODCALLTYPE d3d12_descriptor_heap_AddRef(ID3D12DescriptorHeap static ULONG STDMETHODCALLTYPE d3d12_descriptor_heap_Release(ID3D12DescriptorHeap *iface) { struct d3d12_descriptor_heap *heap = impl_from_ID3D12DescriptorHeap(iface); - ULONG refcount = InterlockedDecrement(&heap->refcount); + unsigned int refcount = vkd3d_atomic_decrement_u32(&heap->refcount); TRACE("%p decreasing refcount to %u.\n", heap, refcount); @@ -4429,7 +4429,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_query_heap_QueryInterface(ID3D12QueryHeap static ULONG STDMETHODCALLTYPE d3d12_query_heap_AddRef(ID3D12QueryHeap *iface) { struct d3d12_query_heap *heap = impl_from_ID3D12QueryHeap(iface); - ULONG refcount = InterlockedIncrement(&heap->refcount); + unsigned int refcount = vkd3d_atomic_increment_u32(&heap->refcount); TRACE("%p increasing refcount to %u.\n", heap, refcount); @@ -4439,7 +4439,7 @@ static ULONG STDMETHODCALLTYPE d3d12_query_heap_AddRef(ID3D12QueryHeap *iface) static ULONG STDMETHODCALLTYPE d3d12_query_heap_Release(ID3D12QueryHeap *iface) { struct d3d12_query_heap *heap = impl_from_ID3D12QueryHeap(iface); - ULONG refcount = InterlockedDecrement(&heap->refcount); + unsigned int refcount = vkd3d_atomic_decrement_u32(&heap->refcount); TRACE("%p decreasing refcount to %u.\n", heap, refcount); diff --git a/libs/vkd3d/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/libs/vkd3d/vkd3d_private.h index a6d5b94b778..92840871631 100644 --- a/libs/vkd3d/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/libs/vkd3d/vkd3d_private.h @@ -192,7 +192,7 @@ struct vkd3d_instance uint64_t host_ticks_per_second; - LONG refcount; + unsigned int refcount; }; #ifdef _WIN32 @@ -665,8 +665,8 @@ VkResult vkd3d_create_timeline_semaphore(const struct d3d12_device *device, uint struct d3d12_heap { ID3D12Heap ID3D12Heap_iface; - LONG refcount; - LONG resource_count; + unsigned int refcount; + unsigned int resource_count; bool is_private; D3D12_HEAP_DESC desc; @@ -721,8 +721,8 @@ struct d3d12_resource_tile_info struct d3d12_resource { ID3D12Resource1 ID3D12Resource1_iface; - LONG refcount; - LONG internal_refcount; + unsigned int refcount; + unsigned int internal_refcount; D3D12_RESOURCE_DESC desc; const struct vkd3d_format *format; @@ -1046,7 +1046,7 @@ struct d3d12_descriptor_heap_vk_set struct d3d12_descriptor_heap { ID3D12DescriptorHeap ID3D12DescriptorHeap_iface; - LONG refcount; + unsigned int refcount; uint64_t serial_id; D3D12_DESCRIPTOR_HEAP_DESC desc; @@ -1085,7 +1085,7 @@ HRESULT d3d12_descriptor_heap_create(struct d3d12_device *device, struct d3d12_query_heap { ID3D12QueryHeap ID3D12QueryHeap_iface; - LONG refcount; + unsigned int refcount; VkQueryPool vk_query_pool; @@ -1749,7 +1749,7 @@ struct vkd3d_desc_object_cache struct d3d12_device { ID3D12Device5 ID3D12Device5_iface; - LONG refcount; + unsigned int refcount; VkDevice vk_device; VkPhysicalDevice vk_physical_device; -- 2.43.0