Mesa (master): radv: Add minimal subgroup support.

Bas Nieuwenhuizen bnieuwenhuizen at kemper.freedesktop.org
Wed Mar 7 20:26:19 UTC 2018


Module: Mesa
Branch: master
Commit: 8f9af587a2dd33580145779275203334d3acdc21
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=8f9af587a2dd33580145779275203334d3acdc21

Author: Bas Nieuwenhuizen <bas at basnieuwenhuizen.nl>
Date:   Sun Jan 21 15:06:10 2018 +0100

radv: Add minimal subgroup support.

Deliberately not implementing workgroup scopes as that is not needed
for core vulkan.

Reviewed-by: Dave Airlie <airlied at redhat.com>

---

 src/amd/common/ac_nir_to_llvm.c | 49 +++++++++++++++++++++++++++++++++++++++++
 src/amd/common/ac_shader_info.c |  2 ++
 src/amd/vulkan/radv_device.c    |  9 ++++++++
 src/amd/vulkan/radv_shader.c    | 10 +++++++++
 4 files changed, 70 insertions(+)

diff --git a/src/amd/common/ac_nir_to_llvm.c b/src/amd/common/ac_nir_to_llvm.c
index f6ad51a412..d02238dba7 100644
--- a/src/amd/common/ac_nir_to_llvm.c
+++ b/src/amd/common/ac_nir_to_llvm.c
@@ -3884,6 +3884,46 @@ visit_load_local_invocation_index(struct ac_nir_context *ctx)
 }
 
 static LLVMValueRef
+visit_load_subgroup_id(struct ac_nir_context *ctx)
+{
+	if (ctx->stage == MESA_SHADER_COMPUTE) {
+		LLVMValueRef result;
+		result = LLVMBuildAnd(ctx->ac.builder, ctx->abi->tg_size,
+				LLVMConstInt(ctx->ac.i32, 0xfc0, false), "");
+		return LLVMBuildLShr(ctx->ac.builder, result,  LLVMConstInt(ctx->ac.i32, 6, false), "");
+	} else {
+		return LLVMConstInt(ctx->ac.i32, 0, false);
+	}
+}
+
+static LLVMValueRef
+visit_load_num_subgroups(struct ac_nir_context *ctx)
+{
+	if (ctx->stage == MESA_SHADER_COMPUTE) {
+		return LLVMBuildAnd(ctx->ac.builder, ctx->abi->tg_size,
+		                    LLVMConstInt(ctx->ac.i32, 0x3f, false), "");
+	} else {
+		return LLVMConstInt(ctx->ac.i32, 1, false);
+	}
+}
+
+static LLVMValueRef
+visit_first_invocation(struct ac_nir_context *ctx)
+{
+	LLVMValueRef active_set = ac_build_ballot(&ctx->ac, ctx->ac.i32_1);
+
+	/* The second argument is whether cttz(0) should be defined, but we do not care. */
+	LLVMValueRef args[] = {active_set, LLVMConstInt(ctx->ac.i1, 0, false)};
+	LLVMValueRef result =  ac_build_intrinsic(&ctx->ac,
+	                                          "llvm.cttz.i64",
+	                                          ctx->ac.i64, args, 2,
+	                                          AC_FUNC_ATTR_NOUNWIND |
+	                                          AC_FUNC_ATTR_READNONE);
+
+	return LLVMBuildTrunc(ctx->ac.builder, result, ctx->ac.i32, "");
+}
+
+static LLVMValueRef
 visit_load_shared(struct ac_nir_context *ctx,
 		   const nir_intrinsic_instr *instr)
 {
@@ -4411,6 +4451,15 @@ static void visit_intrinsic(struct ac_nir_context *ctx,
 	case nir_intrinsic_load_local_invocation_index:
 		result = visit_load_local_invocation_index(ctx);
 		break;
+	case nir_intrinsic_load_subgroup_id:
+		result = visit_load_subgroup_id(ctx);
+		break;
+	case nir_intrinsic_load_num_subgroups:
+		result = visit_load_num_subgroups(ctx);
+		break;
+	case nir_intrinsic_first_invocation:
+		result = visit_first_invocation(ctx);
+		break;
 	case nir_intrinsic_load_push_constant:
 		result = visit_load_push_constant(ctx, instr);
 		break;
diff --git a/src/amd/common/ac_shader_info.c b/src/amd/common/ac_shader_info.c
index 98de963147..883358faaa 100644
--- a/src/amd/common/ac_shader_info.c
+++ b/src/amd/common/ac_shader_info.c
@@ -61,6 +61,8 @@ gather_intrinsic_info(const nir_shader *nir, const nir_intrinsic_instr *instr,
 		break;
 	}
 	case nir_intrinsic_load_local_invocation_index:
+	case nir_intrinsic_load_subgroup_id:
+	case nir_intrinsic_load_num_subgroups:
 		info->cs.uses_local_invocation_idx = true;
 		break;
 	case nir_intrinsic_load_sample_id:
diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c
index 0e584fc9dc..00bb70612e 100644
--- a/src/amd/vulkan/radv_device.c
+++ b/src/amd/vulkan/radv_device.c
@@ -866,6 +866,15 @@ void radv_GetPhysicalDeviceProperties2(
 			properties->minImportedHostPointerAlignment = 4096;
 			break;
 		}
+		case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES: {
+			VkPhysicalDeviceSubgroupProperties *properties =
+			    (VkPhysicalDeviceSubgroupProperties*)ext;
+			properties->subgroupSize = 64;
+			properties->supportedStages = VK_SHADER_STAGE_ALL;
+			properties->supportedOperations = VK_SUBGROUP_FEATURE_BASIC_BIT;
+			properties->quadOperationsInAllStages = false;
+			break;
+		}
 		default:
 			break;
 		}
diff --git a/src/amd/vulkan/radv_shader.c b/src/amd/vulkan/radv_shader.c
index 8a241f8ec8..1e20aa6f9a 100644
--- a/src/amd/vulkan/radv_shader.c
+++ b/src/amd/vulkan/radv_shader.c
@@ -210,6 +210,7 @@ radv_shader_compile_to_nir(struct radv_device *device,
 				.tessellation = true,
 				.int64 = true,
 				.multiview = true,
+				.subgroup_basic = true,
 				.variable_pointers = true,
 			},
 		};
@@ -266,6 +267,15 @@ radv_shader_compile_to_nir(struct radv_device *device,
 	nir_lower_global_vars_to_local(nir);
 	nir_remove_dead_variables(nir, nir_var_local);
 	ac_lower_indirect_derefs(nir, device->physical_device->rad_info.chip_class);
+	nir_lower_subgroups(nir, &(struct nir_lower_subgroups_options) {
+			.subgroup_size = 64,
+			.ballot_bit_size = 64,
+			.lower_to_scalar = 1,
+			.lower_subgroup_masks = 1,
+			.lower_shuffle = 1,
+			.lower_quad =  1,
+		});
+
 	radv_optimize_nir(nir);
 
 	return nir;




More information about the mesa-commit mailing list