From 5363730e175b9de920f29e22a3d368ba142a74d8 Mon Sep 17 00:00:00 2001 From: Elizabeth Figura Date: Sat, 9 Aug 2025 13:03:43 -0500 Subject: [PATCH] vkd3d-shader: Lower BEM instructions. This requires an interface to specify bump mapping constants. --- include/vkd3d_shader.h | 29 ++++++++++++++++++ libs/vkd3d-shader/ir.c | 67 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index df1f5d525..c60044496 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -961,6 +961,35 @@ enum vkd3d_shader_parameter_name * \since 1.15 */ VKD3D_SHADER_PARAMETER_NAME_FOG_SOURCE, + /** + * Bump-mapping matrix. This parameter is used in the evaluation of the + * Shader Model 1.x instructions BEM, TEXBEM, and TEXBEML. + * + * This parameter specifies a 2x2 matrix, packed into a vector in the order + * [00, 01, 10, 11], where "01" specifies the component at column 0 and row + * 1. These coordinates correspond to the Direct3D notation. + * + * To use this parameter to implement Direct3D bump mapping, pass the values + * of the texture stage states D3DTSS_BUMPENVMAT00, D3DTSS_BUMPENVMAT01, + * D3DTSS_BUMPENVMAT10, and D3DTSS_BUMPENVMAT11, in that order. + * + * These enum values are contiguous and arithmetic may safely be performed + * on them. That is, VKD3D_SHADER_PARAMETER_NAME_BUMP_MATRIX_[n] is + * VKD3D_SHADER_PARAMETER_NAME_BUMP_MATRIX_0 plus n. + * + * The data type for each parameter must be + * VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4. + * + * The default value for each parameter is the zero matrix [0, 0; 0, 0]. + * + * \since 1.18 + */ + VKD3D_SHADER_PARAMETER_NAME_BUMP_MATRIX_0, + VKD3D_SHADER_PARAMETER_NAME_BUMP_MATRIX_1, + VKD3D_SHADER_PARAMETER_NAME_BUMP_MATRIX_2, + VKD3D_SHADER_PARAMETER_NAME_BUMP_MATRIX_3, + VKD3D_SHADER_PARAMETER_NAME_BUMP_MATRIX_4, + VKD3D_SHADER_PARAMETER_NAME_BUMP_MATRIX_5, VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_PARAMETER_NAME), }; diff --git a/libs/vkd3d-shader/ir.c b/libs/vkd3d-shader/ir.c index 000c78aee..b46662bb7 100644 --- a/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d-shader/ir.c @@ -2010,6 +2010,69 @@ static enum vkd3d_result vsir_program_lower_texcoord(struct vsir_program *progra return VKD3D_OK; } +static struct vkd3d_shader_instruction *generate_bump_coords(struct vsir_program *program, + struct vsir_program_iterator *it, uint32_t idx, const struct vkd3d_shader_src_param *coords, + const struct vkd3d_shader_src_param *perturbation, const struct vkd3d_shader_location *loc) +{ + struct vkd3d_shader_instruction *ins; + uint32_t ssa_temp, ssa_coords; + + /* We generate the following code: + * + * mad srTMP.xy, PERTURBATION.xx, BUMP_MATRIX#.xy, COORDS.xy + * mad srCOORDS.xy, PERTURBATION.yy, BUMP_MATRIX#.zw, srTMP.xy + */ + + ssa_temp = program->ssa_count++; + ssa_coords = program->ssa_count++; + + ins = vsir_program_iterator_current(it); + if (!vsir_instruction_init_with_params(program, ins, loc, VSIR_OP_MAD, 1, 3)) + return false; + dst_param_init_ssa_float4(&ins->dst[0], ssa_temp); + ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1; + ins->src[0] = *perturbation; + ins->src[0].swizzle = vsir_combine_swizzles(perturbation->swizzle, VKD3D_SHADER_SWIZZLE(X, X, X, X)); + src_param_init_parameter_vec4(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_BUMP_MATRIX_0 + idx, VSIR_DATA_F32); + ins->src[2] = *coords; + + ins = vsir_program_iterator_next(it); + if (!vsir_instruction_init_with_params(program, ins, loc, VSIR_OP_MAD, 1, 3)) + return false; + dst_param_init_ssa_float4(&ins->dst[0], ssa_coords); + ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1; + ins->src[0] = *perturbation; + ins->src[0].swizzle = vsir_combine_swizzles(perturbation->swizzle, VKD3D_SHADER_SWIZZLE(Y, Y, Y, Y)); + src_param_init_parameter_vec4(&ins->src[1], VKD3D_SHADER_PARAMETER_NAME_BUMP_MATRIX_0 + idx, VSIR_DATA_F32); + ins->src[1].swizzle = VKD3D_SHADER_SWIZZLE(Z, W, W, W); + src_param_init_ssa_float4(&ins->src[2], ssa_temp); + ins->src[2].swizzle = VKD3D_SHADER_SWIZZLE(X, Y, Y, Y); + + return ins; +} + +static enum vkd3d_result vsir_program_lower_bem(struct vsir_program *program, struct vsir_program_iterator *it) +{ + struct vkd3d_shader_instruction *ins = vsir_program_iterator_current(it); + const struct vkd3d_shader_location location = ins->location; + const struct vkd3d_shader_src_param *src = ins->src; + const struct vkd3d_shader_dst_param *dst = ins->dst; + + /* bem DST.xy, SRC0, SRC1 + * -> + * mad srTMP.xy, SRC1.xx, BUMP_MATRIX#.xy, SRC0.xy + * mad DST.xy, SRC1.yy, BUMP_MATRIX#.zw, srTMP.xy */ + + if (!vsir_program_iterator_insert_after(it, 1)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + if (!(ins = generate_bump_coords(program, it, dst[0].reg.idx[0].offset, &src[0], &src[1], &location))) + return VKD3D_ERROR_OUT_OF_MEMORY; + + ins->dst[0] = dst[0]; + return VKD3D_OK; +} + static enum vkd3d_result vsir_program_lower_dcl_input(struct vsir_program *program, struct vkd3d_shader_instruction *ins, struct vsir_transformation_context *ctx) { @@ -2094,6 +2157,10 @@ static enum vkd3d_result vsir_program_lower_d3dbc_instructions(struct vsir_progr switch (ins->opcode) { + case VSIR_OP_BEM: + ret = vsir_program_lower_bem(program, &it); + break; + case VSIR_OP_IFC: ret = vsir_program_lower_ifc(program, &it, &tmp_idx, message_context); break;