diff --git a/src/amd/llvm/ac_nir_to_llvm.c b/src/amd/llvm/ac_nir_to_llvm.c index 8551b908f85..64eb62a4a59 100644 --- a/src/amd/llvm/ac_nir_to_llvm.c +++ b/src/amd/llvm/ac_nir_to_llvm.c @@ -3304,6 +3304,30 @@ static LLVMValueRef visit_load(struct ac_nir_context *ctx, nir_intrinsic_instr * return LLVMBuildBitCast(ctx->ac.builder, result, dest_type, ""); } +static LLVMValueRef +emit_load_frag_shading_rate(struct ac_nir_context *ctx) +{ + LLVMValueRef x_rate, y_rate, cond; + + /* VRS Rate X = Ancillary[2:3] + * VRS Rate Y = Ancillary[4:5] + */ + x_rate = ac_unpack_param(&ctx->ac, ac_get_arg(&ctx->ac, ctx->args->ancillary), 2, 2); + y_rate = ac_unpack_param(&ctx->ac, ac_get_arg(&ctx->ac, ctx->args->ancillary), 4, 2); + + /* xRate = xRate == 0x1 ? Horizontal2Pixels : None. */ + cond = LLVMBuildICmp(ctx->ac.builder, LLVMIntEQ, x_rate, ctx->ac.i32_1, ""); + x_rate = LLVMBuildSelect(ctx->ac.builder, cond, + LLVMConstInt(ctx->ac.i32, 4, false), ctx->ac.i32_0, ""); + + /* yRate = yRate == 0x1 ? Vertical2Pixels : None. */ + cond = LLVMBuildICmp(ctx->ac.builder, LLVMIntEQ, y_rate, ctx->ac.i32_1, ""); + y_rate = LLVMBuildSelect(ctx->ac.builder, cond, + LLVMConstInt(ctx->ac.i32, 1, false), ctx->ac.i32_0, ""); + + return LLVMBuildOr(ctx->ac.builder, x_rate, y_rate, ""); +} + static void visit_intrinsic(struct ac_nir_context *ctx, nir_intrinsic_instr *instr) { LLVMValueRef result = NULL; @@ -3405,6 +3429,9 @@ static void visit_intrinsic(struct ac_nir_context *ctx, nir_intrinsic_instr *ins result = ac_to_integer(&ctx->ac, ac_build_gather_values(&ctx->ac, values, 4)); break; } + case nir_intrinsic_load_frag_shading_rate: + result = emit_load_frag_shading_rate(ctx); + break; case nir_intrinsic_load_layer_id: result = ctx->abi->inputs[ac_llvm_reg_index_soa(VARYING_SLOT_LAYER, 0)]; break; diff --git a/src/amd/vulkan/radv_nir_to_llvm.c b/src/amd/vulkan/radv_nir_to_llvm.c index f52953f6b04..129cf9dec66 100644 --- a/src/amd/vulkan/radv_nir_to_llvm.c +++ b/src/amd/vulkan/radv_nir_to_llvm.c @@ -1747,6 +1747,7 @@ radv_llvm_export_vs(struct radv_shader_context *ctx, bool export_clip_dists) { LLVMValueRef psize_value = NULL, layer_value = NULL, viewport_value = NULL; + LLVMValueRef primitive_shading_rate = NULL; struct ac_export_args pos_args[4] = {0}; unsigned pos_idx, index; int i; @@ -1767,6 +1768,9 @@ radv_llvm_export_vs(struct radv_shader_context *ctx, case VARYING_SLOT_VIEWPORT: viewport_value = outputs[i].values[0]; break; + case VARYING_SLOT_PRIMITIVE_SHADING_RATE: + primitive_shading_rate = outputs[i].values[0]; + break; case VARYING_SLOT_CLIP_DIST0: case VARYING_SLOT_CLIP_DIST1: index = 2 + outputs[i].slot_index; @@ -1794,8 +1798,11 @@ radv_llvm_export_vs(struct radv_shader_context *ctx, if (outinfo->writes_pointsize || outinfo->writes_layer || - outinfo->writes_viewport_index) { + outinfo->writes_layer || + outinfo->writes_viewport_index || + outinfo->writes_primitive_shading_rate) { pos_args[1].enabled_channels = ((outinfo->writes_pointsize == true ? 1 : 0) | + (outinfo->writes_primitive_shading_rate == true ? 2 : 0) | (outinfo->writes_layer == true ? 4 : 0)); pos_args[1].valid_mask = 0; pos_args[1].done = 0; @@ -1830,6 +1837,38 @@ radv_llvm_export_vs(struct radv_shader_context *ctx, pos_args[1].enabled_channels |= 1 << 3; } } + + if (outinfo->writes_primitive_shading_rate) { + LLVMValueRef v = ac_to_integer(&ctx->ac, primitive_shading_rate); + LLVMValueRef cond; + + /* xRate = (shadingRate & (Horizontal2Pixels | Horizontal4Pixels)) ? 0x1 : 0x0; */ + LLVMValueRef x_rate = + LLVMBuildAnd(ctx->ac.builder, v, + LLVMConstInt(ctx->ac.i32, 4 | 8, false), ""); + cond = LLVMBuildICmp(ctx->ac.builder, LLVMIntNE, x_rate, ctx->ac.i32_0, ""); + x_rate = LLVMBuildSelect(ctx->ac.builder, cond, + ctx->ac.i32_1, ctx->ac.i32_0, ""); + + /* yRate = (shadingRate & (Vertical2Pixels | Vertical4Pixels)) ? 0x1 : 0x0; */ + LLVMValueRef y_rate = + LLVMBuildAnd(ctx->ac.builder, v, + LLVMConstInt(ctx->ac.i32, 1 | 2, false), ""); + cond = LLVMBuildICmp(ctx->ac.builder, LLVMIntNE, y_rate, ctx->ac.i32_0, ""); + y_rate = LLVMBuildSelect(ctx->ac.builder, cond, + ctx->ac.i32_1, ctx->ac.i32_0, ""); + + /* Bits [2:3] = VRS rate X + * Bits [4:5] = VRS rate Y + * HW shading rate = (xRate << 2) | (yRate << 4) + */ + v = LLVMBuildOr(ctx->ac.builder, + LLVMBuildShl(ctx->ac.builder, x_rate, + LLVMConstInt(ctx->ac.i32, 2, false), ""), + LLVMBuildShl(ctx->ac.builder, y_rate, + LLVMConstInt(ctx->ac.i32, 4, false), ""), ""); + pos_args[1].out[1] = ac_to_float(&ctx->ac, v); + } } for (i = 0; i < 4; i++) {