diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index e57769f5..d830c401 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -5175,6 +5175,10 @@ static bool intrinsic_GetRenderTargetSampleCount(struct hlsl_ctx *ctx, struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {0}; struct hlsl_ir_node *expr; + if (ctx->profile->type != VKD3D_SHADER_TYPE_PIXEL || hlsl_version_lt(ctx, 4, 1)) + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, + "GetRenderTargetSampleCount() can only be used from a pixel shader using version 4.1 or higher."); + if (!(expr = hlsl_new_expr(ctx, HLSL_OP0_RASTERIZER_SAMPLE_COUNT, operands, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), loc))) return false; diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 0ef64b66..8cb4b0f0 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -6817,6 +6817,16 @@ static void vsir_src_from_hlsl_node(struct vkd3d_shader_src_param *src, } } +static void vsir_dst_from_hlsl_node(struct vkd3d_shader_dst_param *dst, + struct hlsl_ctx *ctx, struct hlsl_ir_node *instr) +{ + VKD3D_ASSERT(instr->reg.allocated); + vsir_dst_param_init(dst, VKD3DSPR_TEMP, vsir_data_type_from_hlsl_instruction(ctx, instr), 1); + dst->reg.idx[0].offset = instr->reg.id; + dst->reg.dimension = VSIR_DIMENSION_VEC4; + dst->write_mask = instr->reg.writemask; +} + static void sm1_generate_vsir_instr_constant(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_constant *constant) { @@ -6842,6 +6852,25 @@ static void sm1_generate_vsir_instr_constant(struct hlsl_ctx *ctx, dst_param->write_mask = instr->reg.writemask; } +static void sm4_generate_vsir_rasterizer_sample_count(struct hlsl_ctx *ctx, + struct vsir_program *program, struct hlsl_ir_expr *expr) +{ + struct vkd3d_shader_src_param *src_param; + struct hlsl_ir_node *instr = &expr->node; + struct vkd3d_shader_instruction *ins; + + if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_SAMPLE_INFO, 1, 1))) + return; + ins->flags = VKD3DSI_SAMPLE_INFO_UINT; + + vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr); + + src_param = &ins->src[0]; + vsir_src_param_init(src_param, VKD3DSPR_RASTERIZER, VKD3D_DATA_UNUSED, 0); + src_param->reg.dimension = VSIR_DIMENSION_VEC4; + src_param->swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); +} + /* Translate ops that can be mapped to a single vsir instruction with only one dst register. */ static void generate_vsir_instr_expr_single_instr_op(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_expr *expr, enum vkd3d_shader_opcode opcode, @@ -6866,10 +6895,7 @@ static void generate_vsir_instr_expr_single_instr_op(struct hlsl_ctx *ctx, return; dst_param = &ins->dst[0]; - vsir_register_init(&dst_param->reg, VKD3DSPR_TEMP, vsir_data_type_from_hlsl_instruction(ctx, instr), 1); - dst_param->reg.idx[0].offset = instr->reg.id; - dst_param->reg.dimension = VSIR_DIMENSION_VEC4; - dst_param->write_mask = instr->reg.writemask; + vsir_dst_from_hlsl_node(dst_param, ctx, instr); dst_param->modifiers = dst_mod; for (i = 0; i < src_count; ++i) @@ -7815,6 +7841,10 @@ static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, switch (expr->op) { + case HLSL_OP0_RASTERIZER_SAMPLE_COUNT: + sm4_generate_vsir_rasterizer_sample_count(ctx, program, expr); + return true; + case HLSL_OP1_ABS: VKD3D_ASSERT(type_is_float(dst_type)); generate_vsir_instr_expr_single_instr_op(ctx, program, expr, VKD3DSIH_MOV, VKD3DSPSM_ABS, 0, true); diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index f8d164f5..3691754a 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -5468,25 +5468,6 @@ static void write_sm4_cast(const struct tpf_compiler *tpf, const struct hlsl_ir_ } } -static void write_sm4_rasterizer_sample_count(const struct tpf_compiler *tpf, const struct hlsl_ir_node *dst) -{ - struct sm4_instruction instr; - - memset(&instr, 0, sizeof(instr)); - instr.opcode = VKD3D_SM4_OP_SAMPLE_INFO; - instr.extra_bits |= VKD3DSI_SAMPLE_INFO_UINT << VKD3D_SM4_INSTRUCTION_FLAGS_SHIFT; - - sm4_dst_from_node(&instr.dsts[0], dst); - instr.dst_count = 1; - - instr.srcs[0].reg.type = VKD3DSPR_RASTERIZER; - instr.srcs[0].reg.dimension = VSIR_DIMENSION_VEC4; - instr.srcs[0].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X); - instr.src_count = 1; - - write_sm4_instruction(tpf, &instr); -} - static void write_sm4_expr(const struct tpf_compiler *tpf, const struct hlsl_ir_expr *expr) { const struct vkd3d_shader_version *version = &tpf->program->shader_version; @@ -5502,14 +5483,6 @@ static void write_sm4_expr(const struct tpf_compiler *tpf, const struct hlsl_ir_ switch (expr->op) { - case HLSL_OP0_RASTERIZER_SAMPLE_COUNT: - if (version->type == VKD3D_SHADER_TYPE_PIXEL && vkd3d_shader_ver_ge(version, 4, 1)) - write_sm4_rasterizer_sample_count(tpf, &expr->node); - else - hlsl_error(tpf->ctx, &expr->node.loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, - "GetRenderTargetSampleCount() can only be used from a pixel shader using version 4.1 or higher."); - break; - case HLSL_OP1_CAST: write_sm4_cast(tpf, expr); break; @@ -6042,6 +6015,7 @@ static void tpf_simple_instruction(struct tpf_compiler *tpf, const struct vkd3d_ } instr.opcode = info->opcode; + instr.extra_bits = ins->flags << VKD3D_SM4_INSTRUCTION_FLAGS_SHIFT; instr.dst_count = ins->dst_count; instr.src_count = ins->src_count; @@ -6137,6 +6111,7 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ case VKD3DSIH_ROUND_PI: case VKD3DSIH_ROUND_Z: case VKD3DSIH_RSQ: + case VKD3DSIH_SAMPLE_INFO: case VKD3DSIH_SQRT: case VKD3DSIH_UGE: case VKD3DSIH_ULT: