intel/compiler: Add support for variable workgroup size
Add new builtin parameters that are used to keep track of the group size. This will be used to implement ARB_compute_variable_group_size. The compiler will use the maximum group size supported to pick a suitable SIMD variant. A later improvement will be to keep all SIMD variants (like FS) so the driver can select the best one at dispatch time. When variable workgroup size is used, the small workgroup optimization is disabled as it we can't prove at compile time that the barriers won't be needed. Extracted from original i965 patch with additional changes by Caio Marcelo de Oliveira Filho. Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4504>
This commit is contained in:
committed by
Caio Marcelo de Oliveira Filho
parent
c54fc0d07b
commit
c77dc51203
@@ -101,11 +101,23 @@ fs_visitor::nir_setup_uniforms()
|
||||
uniforms = nir->num_uniforms / 4;
|
||||
|
||||
if (stage == MESA_SHADER_COMPUTE) {
|
||||
/* Add a uniform for the thread local id. It must be the last uniform
|
||||
* on the list.
|
||||
*/
|
||||
/* Add uniforms for builtins after regular NIR uniforms. */
|
||||
assert(uniforms == prog_data->nr_params);
|
||||
uint32_t *param = brw_stage_prog_data_add_params(prog_data, 1);
|
||||
|
||||
uint32_t *param;
|
||||
if (brw_cs_prog_data(prog_data)->uses_variable_group_size) {
|
||||
param = brw_stage_prog_data_add_params(prog_data, 3);
|
||||
for (unsigned i = 0; i < 3; i++) {
|
||||
param[i] = (BRW_PARAM_BUILTIN_WORK_GROUP_SIZE_X + i);
|
||||
group_size[i] = fs_reg(UNIFORM, uniforms++, BRW_REGISTER_TYPE_UD);
|
||||
}
|
||||
}
|
||||
|
||||
/* Subgroup ID must be the last uniform on the list. This will make
|
||||
* easier later to split between cross thread and per thread
|
||||
* uniforms.
|
||||
*/
|
||||
param = brw_stage_prog_data_add_params(prog_data, 1);
|
||||
*param = BRW_PARAM_BUILTIN_SUBGROUP_ID;
|
||||
subgroup_id = fs_reg(UNIFORM, uniforms++, BRW_REGISTER_TYPE_UD);
|
||||
}
|
||||
@@ -3814,7 +3826,8 @@ fs_visitor::nir_emit_cs_intrinsic(const fs_builder &bld,
|
||||
* invocations are already executed lock-step. Instead of an actual
|
||||
* barrier just emit a scheduling fence, that will generate no code.
|
||||
*/
|
||||
if (workgroup_size() <= dispatch_width) {
|
||||
if (!cs_prog_data->uses_variable_group_size &&
|
||||
workgroup_size() <= dispatch_width) {
|
||||
bld.exec_all().group(1, 0).emit(FS_OPCODE_SCHEDULING_FENCE);
|
||||
break;
|
||||
}
|
||||
@@ -3949,6 +3962,14 @@ fs_visitor::nir_emit_cs_intrinsic(const fs_builder &bld,
|
||||
break;
|
||||
}
|
||||
|
||||
case nir_intrinsic_load_local_group_size: {
|
||||
for (unsigned i = 0; i < 3; i++) {
|
||||
bld.MOV(retype(offset(dest, bld, i), BRW_REGISTER_TYPE_UD),
|
||||
group_size[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
nir_emit_intrinsic(bld, instr);
|
||||
break;
|
||||
@@ -4337,7 +4358,8 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr
|
||||
*
|
||||
* TODO: Check if applies for many HW threads sharing same Data Port.
|
||||
*/
|
||||
if (slm_fence && workgroup_size() <= dispatch_width)
|
||||
if (!brw_cs_prog_data(prog_data)->uses_variable_group_size &&
|
||||
slm_fence && workgroup_size() <= dispatch_width)
|
||||
slm_fence = false;
|
||||
|
||||
/* Prior to Gen11, there's only L3 fence, so emit that instead. */
|
||||
|
||||
Reference in New Issue
Block a user