LLVMValueRef push_constants;
LLVMValueRef view_index;
LLVMValueRef num_work_groups;
- LLVMValueRef workgroup_ids;
+ LLVMValueRef workgroup_ids[3];
LLVMValueRef local_invocation_ids;
LLVMValueRef tg_size;
LLVMValueRef oc_lds;
LLVMValueRef merged_wave_info;
LLVMValueRef tess_factor_offset;
- LLVMValueRef tcs_patch_id;
- LLVMValueRef tcs_rel_ids;
LLVMValueRef tes_rel_patch_id;
- LLVMValueRef tes_patch_id;
LLVMValueRef tes_u;
LLVMValueRef tes_v;
LLVMValueRef *assign[MAX_ARGS];
unsigned array_params_mask;
uint8_t count;
- uint8_t user_sgpr_count;
uint8_t sgpr_count;
- uint8_t num_user_sgprs_used;
uint8_t num_sgprs_used;
uint8_t num_vgprs_used;
};
-static inline void
-add_argument(struct arg_info *info,
- LLVMTypeRef type, LLVMValueRef *param_ptr)
+enum ac_arg_regfile {
+ ARG_SGPR,
+ ARG_VGPR,
+};
+
+static void
+add_arg(struct arg_info *info, enum ac_arg_regfile regfile, LLVMTypeRef type,
+ LLVMValueRef *param_ptr)
{
assert(info->count < MAX_ARGS);
+
info->assign[info->count] = param_ptr;
info->types[info->count] = type;
info->count++;
-}
-
-static inline void
-add_sgpr_argument(struct arg_info *info,
- LLVMTypeRef type, LLVMValueRef *param_ptr)
-{
- add_argument(info, type, param_ptr);
- info->num_sgprs_used += ac_get_type_size(type) / 4;
- info->sgpr_count++;
-}
-
-static inline void
-add_user_sgpr_argument(struct arg_info *info,
- LLVMTypeRef type,
- LLVMValueRef *param_ptr)
-{
- add_sgpr_argument(info, type, param_ptr);
- info->num_user_sgprs_used += ac_get_type_size(type) / 4;
- info->user_sgpr_count++;
-}
-static inline void
-add_vgpr_argument(struct arg_info *info,
- LLVMTypeRef type,
- LLVMValueRef *param_ptr)
-{
- add_argument(info, type, param_ptr);
- info->num_vgprs_used += ac_get_type_size(type) / 4;
+ if (regfile == ARG_SGPR) {
+ info->num_sgprs_used += ac_get_type_size(type) / 4;
+ info->sgpr_count++;
+ } else {
+ assert(regfile == ARG_VGPR);
+ info->num_vgprs_used += ac_get_type_size(type) / 4;
+ }
}
static inline void
-add_user_sgpr_array_argument(struct arg_info *info,
- LLVMTypeRef type,
- LLVMValueRef *param_ptr)
+add_array_arg(struct arg_info *info, LLVMTypeRef type, LLVMValueRef *param_ptr)
{
info->array_params_mask |= (1 << info->count);
- add_user_sgpr_argument(info, type, param_ptr);
+ add_arg(info, ARG_SGPR, type, param_ptr);
}
static void assign_arguments(LLVMValueRef main_function,
{
switch (ctx->stage) {
case MESA_SHADER_TESS_CTRL:
- return unpack_param(&ctx->ac, ctx->tcs_rel_ids, 0, 8);
+ return unpack_param(&ctx->ac, ctx->abi.tcs_rel_ids, 0, 8);
case MESA_SHADER_TESS_EVAL:
return ctx->tes_rel_patch_id;
break;
"");
}
-static void set_userdata_location(struct ac_userdata_info *ud_info, uint8_t *sgpr_idx, uint8_t num_sgprs)
+static void
+set_loc(struct ac_userdata_info *ud_info, uint8_t *sgpr_idx, uint8_t num_sgprs,
+ uint32_t indirect_offset)
{
ud_info->sgpr_idx = *sgpr_idx;
ud_info->num_sgprs = num_sgprs;
- ud_info->indirect = false;
- ud_info->indirect_offset = 0;
+ ud_info->indirect = indirect_offset > 0;
+ ud_info->indirect_offset = indirect_offset;
*sgpr_idx += num_sgprs;
}
-static void set_userdata_location_shader(struct nir_to_llvm_context *ctx,
- int idx, uint8_t *sgpr_idx, uint8_t num_sgprs)
+static void
+set_loc_shader(struct nir_to_llvm_context *ctx, int idx, uint8_t *sgpr_idx,
+ uint8_t num_sgprs)
{
- set_userdata_location(&ctx->shader_info->user_sgprs_locs.shader_data[idx], sgpr_idx, num_sgprs);
-}
+ struct ac_userdata_info *ud_info =
+ &ctx->shader_info->user_sgprs_locs.shader_data[idx];
+ assert(ud_info);
+ set_loc(ud_info, sgpr_idx, num_sgprs, 0);
+}
-static void set_userdata_location_indirect(struct ac_userdata_info *ud_info, uint8_t sgpr_idx, uint8_t num_sgprs,
- uint32_t indirect_offset)
+static void
+set_loc_desc(struct nir_to_llvm_context *ctx, int idx, uint8_t *sgpr_idx,
+ uint32_t indirect_offset)
{
- ud_info->sgpr_idx = sgpr_idx;
- ud_info->num_sgprs = num_sgprs;
- ud_info->indirect = true;
- ud_info->indirect_offset = indirect_offset;
+ struct ac_userdata_info *ud_info =
+ &ctx->shader_info->user_sgprs_locs.descriptor_sets[idx];
+ assert(ud_info);
+
+ set_loc(ud_info, sgpr_idx, 2, indirect_offset);
}
struct user_sgpr_info {
};
static void allocate_user_sgprs(struct nir_to_llvm_context *ctx,
+ gl_shader_stage stage,
struct user_sgpr_info *user_sgpr_info)
{
memset(user_sgpr_info, 0, sizeof(struct user_sgpr_info));
/* until we sort out scratch/global buffers always assign ring offsets for gs/vs/es */
- if (ctx->stage == MESA_SHADER_GEOMETRY ||
- ctx->stage == MESA_SHADER_VERTEX ||
- ctx->stage == MESA_SHADER_TESS_CTRL ||
- ctx->stage == MESA_SHADER_TESS_EVAL ||
+ if (stage == MESA_SHADER_GEOMETRY ||
+ stage == MESA_SHADER_VERTEX ||
+ stage == MESA_SHADER_TESS_CTRL ||
+ stage == MESA_SHADER_TESS_EVAL ||
ctx->is_gs_copy_shader)
user_sgpr_info->need_ring_offsets = true;
- if (ctx->stage == MESA_SHADER_FRAGMENT &&
+ if (stage == MESA_SHADER_FRAGMENT &&
ctx->shader_info->info.ps.needs_sample_positions)
user_sgpr_info->need_ring_offsets = true;
user_sgpr_info->sgpr_count += 2;
}
- switch (ctx->stage) {
+ /* FIXME: fix the number of user sgprs for merged shaders on GFX9 */
+ switch (stage) {
case MESA_SHADER_COMPUTE:
if (ctx->shader_info->info.cs.uses_grid_size)
user_sgpr_info->sgpr_count += 3;
break;
}
- if (ctx->shader_info->info.needs_push_constants)
+ if (ctx->shader_info->info.loads_push_constants)
user_sgpr_info->sgpr_count += 2;
- uint32_t remaining_sgprs = 16 - user_sgpr_info->sgpr_count;
+ uint32_t available_sgprs = ctx->options->chip_class >= GFX9 ? 32 : 16;
+ uint32_t remaining_sgprs = available_sgprs - user_sgpr_info->sgpr_count;
+
if (remaining_sgprs / 2 < util_bitcount(ctx->shader_info->info.desc_set_used_mask)) {
user_sgpr_info->sgpr_count += 2;
user_sgpr_info->indirect_all_descriptor_sets = true;
}
static void
-radv_define_common_user_sgprs_phase1(struct nir_to_llvm_context *ctx,
- gl_shader_stage stage,
- bool has_previous_stage,
- gl_shader_stage previous_stage,
- const struct user_sgpr_info *user_sgpr_info,
- struct arg_info *args,
- LLVMValueRef *desc_sets)
-{
- unsigned num_sets = ctx->options->layout ? ctx->options->layout->num_sets : 0;
+declare_global_input_sgprs(struct nir_to_llvm_context *ctx,
+ gl_shader_stage stage,
+ bool has_previous_stage,
+ gl_shader_stage previous_stage,
+ const struct user_sgpr_info *user_sgpr_info,
+ struct arg_info *args,
+ LLVMValueRef *desc_sets)
+{
+ LLVMTypeRef type = const_array(ctx->ac.i8, 1024 * 1024);
+ unsigned num_sets = ctx->options->layout ?
+ ctx->options->layout->num_sets : 0;
unsigned stage_mask = 1 << stage;
+
if (has_previous_stage)
stage_mask |= 1 << previous_stage;
if (!user_sgpr_info->indirect_all_descriptor_sets) {
for (unsigned i = 0; i < num_sets; ++i) {
if (ctx->options->layout->set[i].layout->shader_stages & stage_mask) {
- add_user_sgpr_array_argument(args, const_array(ctx->ac.i8, 1024 * 1024), &ctx->descriptor_sets[i]);
+ add_array_arg(args, type,
+ &ctx->descriptor_sets[i]);
}
}
- } else
- add_user_sgpr_array_argument(args, const_array(const_array(ctx->ac.i8, 1024 * 1024), 32), desc_sets);
+ } else {
+ add_array_arg(args, const_array(type, 32), desc_sets);
+ }
- if (ctx->shader_info->info.needs_push_constants) {
+ if (ctx->shader_info->info.loads_push_constants) {
/* 1 for push constants and dynamic descriptors */
- add_user_sgpr_array_argument(args, const_array(ctx->ac.i8, 1024 * 1024), &ctx->push_constants);
+ add_array_arg(args, type, &ctx->push_constants);
+ }
+}
+
+static void
+declare_vs_specific_input_sgprs(struct nir_to_llvm_context *ctx,
+ gl_shader_stage stage,
+ bool has_previous_stage,
+ gl_shader_stage previous_stage,
+ struct arg_info *args)
+{
+ if (!ctx->is_gs_copy_shader &&
+ (stage == MESA_SHADER_VERTEX ||
+ (has_previous_stage && previous_stage == MESA_SHADER_VERTEX))) {
+ if (ctx->shader_info->info.vs.has_vertex_buffers) {
+ add_arg(args, ARG_SGPR, const_array(ctx->ac.v4i32, 16),
+ &ctx->vertex_buffers);
+ }
+ add_arg(args, ARG_SGPR, ctx->ac.i32, &ctx->abi.base_vertex);
+ add_arg(args, ARG_SGPR, ctx->ac.i32, &ctx->abi.start_instance);
+ if (ctx->shader_info->info.vs.needs_draw_id) {
+ add_arg(args, ARG_SGPR, ctx->ac.i32, &ctx->abi.draw_id);
+ }
}
}
static void
-radv_define_common_user_sgprs_phase2(struct nir_to_llvm_context *ctx,
- gl_shader_stage stage,
- bool has_previous_stage,
- gl_shader_stage previous_stage,
- const struct user_sgpr_info *user_sgpr_info,
- LLVMValueRef desc_sets,
- uint8_t *user_sgpr_idx)
-{
- unsigned num_sets = ctx->options->layout ? ctx->options->layout->num_sets : 0;
+declare_vs_input_vgprs(struct nir_to_llvm_context *ctx, struct arg_info *args)
+{
+ add_arg(args, ARG_VGPR, ctx->ac.i32, &ctx->abi.vertex_id);
+ if (!ctx->is_gs_copy_shader) {
+ if (ctx->options->key.vs.as_ls) {
+ add_arg(args, ARG_VGPR, ctx->ac.i32, &ctx->rel_auto_id);
+ add_arg(args, ARG_VGPR, ctx->ac.i32, &ctx->abi.instance_id);
+ } else {
+ add_arg(args, ARG_VGPR, ctx->ac.i32, &ctx->abi.instance_id);
+ add_arg(args, ARG_VGPR, ctx->ac.i32, &ctx->vs_prim_id);
+ }
+ add_arg(args, ARG_VGPR, ctx->ac.i32, NULL); /* unused */
+ }
+}
+
+static void
+declare_tes_input_vgprs(struct nir_to_llvm_context *ctx, struct arg_info *args)
+{
+ add_arg(args, ARG_VGPR, ctx->ac.f32, &ctx->tes_u);
+ add_arg(args, ARG_VGPR, ctx->ac.f32, &ctx->tes_v);
+ add_arg(args, ARG_VGPR, ctx->ac.i32, &ctx->tes_rel_patch_id);
+ add_arg(args, ARG_VGPR, ctx->ac.i32, &ctx->abi.tes_patch_id);
+}
+
+static void
+set_global_input_locs(struct nir_to_llvm_context *ctx, gl_shader_stage stage,
+ bool has_previous_stage, gl_shader_stage previous_stage,
+ const struct user_sgpr_info *user_sgpr_info,
+ LLVMValueRef desc_sets, uint8_t *user_sgpr_idx)
+{
+ unsigned num_sets = ctx->options->layout ?
+ ctx->options->layout->num_sets : 0;
unsigned stage_mask = 1 << stage;
+
if (has_previous_stage)
stage_mask |= 1 << previous_stage;
if (!user_sgpr_info->indirect_all_descriptor_sets) {
for (unsigned i = 0; i < num_sets; ++i) {
if (ctx->options->layout->set[i].layout->shader_stages & stage_mask) {
- set_userdata_location(&ctx->shader_info->user_sgprs_locs.descriptor_sets[i], user_sgpr_idx, 2);
+ set_loc_desc(ctx, i, user_sgpr_idx, 0);
} else
ctx->descriptor_sets[i] = NULL;
}
} else {
- uint32_t desc_sgpr_idx = *user_sgpr_idx;
- set_userdata_location_shader(ctx, AC_UD_INDIRECT_DESCRIPTOR_SETS, user_sgpr_idx, 2);
+ set_loc_shader(ctx, AC_UD_INDIRECT_DESCRIPTOR_SETS,
+ user_sgpr_idx, 2);
for (unsigned i = 0; i < num_sets; ++i) {
if (ctx->options->layout->set[i].layout->shader_stages & stage_mask) {
- set_userdata_location_indirect(&ctx->shader_info->user_sgprs_locs.descriptor_sets[i], desc_sgpr_idx, 2, i * 8);
- ctx->descriptor_sets[i] = ac_build_load_to_sgpr(&ctx->ac, desc_sets, LLVMConstInt(ctx->ac.i32, i, false));
+ set_loc_desc(ctx, i, user_sgpr_idx, i * 8);
+ ctx->descriptor_sets[i] =
+ ac_build_load_to_sgpr(&ctx->ac,
+ desc_sets,
+ LLVMConstInt(ctx->ac.i32, i, false));
} else
ctx->descriptor_sets[i] = NULL;
ctx->shader_info->need_indirect_descriptor_sets = true;
}
- if (ctx->shader_info->info.needs_push_constants) {
- set_userdata_location_shader(ctx, AC_UD_PUSH_CONSTANTS, user_sgpr_idx, 2);
+ if (ctx->shader_info->info.loads_push_constants) {
+ set_loc_shader(ctx, AC_UD_PUSH_CONSTANTS, user_sgpr_idx, 2);
}
}
static void
-radv_define_vs_user_sgprs_phase1(struct nir_to_llvm_context *ctx,
- gl_shader_stage stage,
- bool has_previous_stage,
- gl_shader_stage previous_stage,
- struct arg_info *args)
-{
- if (!ctx->is_gs_copy_shader && (stage == MESA_SHADER_VERTEX || (has_previous_stage && previous_stage == MESA_SHADER_VERTEX))) {
- if (ctx->shader_info->info.vs.has_vertex_buffers)
- add_user_sgpr_argument(args, const_array(ctx->ac.v4i32, 16), &ctx->vertex_buffers); /* vertex buffers */
- add_user_sgpr_argument(args, ctx->ac.i32, &ctx->abi.base_vertex); // base vertex
- add_user_sgpr_argument(args, ctx->ac.i32, &ctx->abi.start_instance);// start instance
- if (ctx->shader_info->info.vs.needs_draw_id)
- add_user_sgpr_argument(args, ctx->ac.i32, &ctx->abi.draw_id); // draw id
- }
-}
-
-static void
-radv_define_vs_user_sgprs_phase2(struct nir_to_llvm_context *ctx,
- gl_shader_stage stage,
- bool has_previous_stage,
- gl_shader_stage previous_stage,
- uint8_t *user_sgpr_idx)
-{
- if (!ctx->is_gs_copy_shader && (stage == MESA_SHADER_VERTEX || (has_previous_stage && previous_stage == MESA_SHADER_VERTEX))) {
+set_vs_specific_input_locs(struct nir_to_llvm_context *ctx,
+ gl_shader_stage stage, bool has_previous_stage,
+ gl_shader_stage previous_stage,
+ uint8_t *user_sgpr_idx)
+{
+ if (!ctx->is_gs_copy_shader &&
+ (stage == MESA_SHADER_VERTEX ||
+ (has_previous_stage && previous_stage == MESA_SHADER_VERTEX))) {
if (ctx->shader_info->info.vs.has_vertex_buffers) {
- set_userdata_location_shader(ctx, AC_UD_VS_VERTEX_BUFFERS, user_sgpr_idx, 2);
+ set_loc_shader(ctx, AC_UD_VS_VERTEX_BUFFERS,
+ user_sgpr_idx, 2);
}
+
unsigned vs_num = 2;
if (ctx->shader_info->info.vs.needs_draw_id)
vs_num++;
- set_userdata_location_shader(ctx, AC_UD_VS_BASE_VERTEX_START_INSTANCE, user_sgpr_idx, vs_num);
+ set_loc_shader(ctx, AC_UD_VS_BASE_VERTEX_START_INSTANCE,
+ user_sgpr_idx, vs_num);
}
}
-
static void create_function(struct nir_to_llvm_context *ctx,
gl_shader_stage stage,
bool has_previous_stage,
struct arg_info args = {};
LLVMValueRef desc_sets;
- allocate_user_sgprs(ctx, &user_sgpr_info);
+ allocate_user_sgprs(ctx, stage, &user_sgpr_info);
if (user_sgpr_info.need_ring_offsets && !ctx->options->supports_spill) {
- add_user_sgpr_argument(&args, const_array(ctx->ac.v4i32, 16), &ctx->ring_offsets); /* address of rings */
+ add_arg(&args, ARG_SGPR, const_array(ctx->ac.v4i32, 16),
+ &ctx->ring_offsets);
}
switch (stage) {
case MESA_SHADER_COMPUTE:
- radv_define_common_user_sgprs_phase1(ctx, stage, has_previous_stage, previous_stage, &user_sgpr_info, &args, &desc_sets);
+ declare_global_input_sgprs(ctx, stage, has_previous_stage,
+ previous_stage, &user_sgpr_info,
+ &args, &desc_sets);
+
if (ctx->shader_info->info.cs.uses_grid_size) {
- add_user_sgpr_argument(&args, ctx->ac.v3i32,
- &ctx->num_work_groups);
+ add_arg(&args, ARG_SGPR, ctx->ac.v3i32,
+ &ctx->num_work_groups);
+ }
+
+ for (int i = 0; i < 3; i++) {
+ ctx->workgroup_ids[i] = NULL;
+ if (ctx->shader_info->info.cs.uses_block_id[i]) {
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->workgroup_ids[i]);
+ }
}
- add_sgpr_argument(&args, ctx->ac.v3i32, &ctx->workgroup_ids);
+
if (ctx->shader_info->info.cs.uses_local_invocation_idx)
- add_sgpr_argument(&args, ctx->ac.i32, &ctx->tg_size);
- add_vgpr_argument(&args, ctx->ac.v3i32, &ctx->local_invocation_ids);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32, &ctx->tg_size);
+ add_arg(&args, ARG_VGPR, ctx->ac.v3i32,
+ &ctx->local_invocation_ids);
break;
case MESA_SHADER_VERTEX:
- radv_define_common_user_sgprs_phase1(ctx, stage, has_previous_stage, previous_stage, &user_sgpr_info, &args, &desc_sets);
- radv_define_vs_user_sgprs_phase1(ctx, stage, has_previous_stage, previous_stage, &args);
+ declare_global_input_sgprs(ctx, stage, has_previous_stage,
+ previous_stage, &user_sgpr_info,
+ &args, &desc_sets);
+ declare_vs_specific_input_sgprs(ctx, stage, has_previous_stage,
+ previous_stage, &args);
+
if (ctx->shader_info->info.needs_multiview_view_index || (!ctx->options->key.vs.as_es && !ctx->options->key.vs.as_ls && ctx->options->key.has_multiview_view_index))
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->view_index);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32, &ctx->view_index);
if (ctx->options->key.vs.as_es)
- add_sgpr_argument(&args, ctx->ac.i32, &ctx->es2gs_offset); // es2gs offset
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->es2gs_offset);
else if (ctx->options->key.vs.as_ls)
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->ls_out_layout); // ls out layout
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->abi.vertex_id); // vertex id
- if (!ctx->is_gs_copy_shader) {
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->rel_auto_id); // rel auto id
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->vs_prim_id); // vs prim id
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->abi.instance_id); // instance id
- }
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->ls_out_layout);
+
+ declare_vs_input_vgprs(ctx, &args);
break;
case MESA_SHADER_TESS_CTRL:
if (has_previous_stage) {
// First 6 system regs
- add_sgpr_argument(&args, ctx->ac.i32, &ctx->oc_lds); // param oc lds
- add_sgpr_argument(&args, ctx->ac.i32, &ctx->merged_wave_info); // merged wave info
- add_sgpr_argument(&args, ctx->ac.i32, &ctx->tess_factor_offset); // tess factor offset
-
- add_sgpr_argument(&args, ctx->ac.i32, NULL); // scratch offset
- add_sgpr_argument(&args, ctx->ac.i32, NULL); // unknown
- add_sgpr_argument(&args, ctx->ac.i32, NULL); // unknown
-
- radv_define_common_user_sgprs_phase1(ctx, stage, has_previous_stage, previous_stage, &user_sgpr_info, &args, &desc_sets);
- radv_define_vs_user_sgprs_phase1(ctx, stage, has_previous_stage, previous_stage, &args);
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->ls_out_layout); // ls out layout
-
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->tcs_offchip_layout); // tcs offchip layout
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->tcs_out_offsets); // tcs out offsets
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->tcs_out_layout); // tcs out layout
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->tcs_in_layout); // tcs in layout
+ add_arg(&args, ARG_SGPR, ctx->ac.i32, &ctx->oc_lds);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->merged_wave_info);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->tess_factor_offset);
+
+ add_arg(&args, ARG_SGPR, ctx->ac.i32, NULL); // scratch offset
+ add_arg(&args, ARG_SGPR, ctx->ac.i32, NULL); // unknown
+ add_arg(&args, ARG_SGPR, ctx->ac.i32, NULL); // unknown
+
+ declare_global_input_sgprs(ctx, stage,
+ has_previous_stage,
+ previous_stage,
+ &user_sgpr_info, &args,
+ &desc_sets);
+ declare_vs_specific_input_sgprs(ctx, stage,
+ has_previous_stage,
+ previous_stage, &args);
+
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->ls_out_layout);
+
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->tcs_offchip_layout);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->tcs_out_offsets);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->tcs_out_layout);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->tcs_in_layout);
if (ctx->shader_info->info.needs_multiview_view_index)
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->view_index);
-
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->tcs_patch_id); // patch id
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->tcs_rel_ids); // rel ids;
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->abi.vertex_id); // vertex id
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->rel_auto_id); // rel auto id
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->vs_prim_id); // vs prim id
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->abi.instance_id); // instance id
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->view_index);
+
+ add_arg(&args, ARG_VGPR, ctx->ac.i32,
+ &ctx->abi.tcs_patch_id);
+ add_arg(&args, ARG_VGPR, ctx->ac.i32,
+ &ctx->abi.tcs_rel_ids);
+
+ declare_vs_input_vgprs(ctx, &args);
} else {
- radv_define_common_user_sgprs_phase1(ctx, stage, has_previous_stage, previous_stage, &user_sgpr_info, &args, &desc_sets);
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->tcs_offchip_layout); // tcs offchip layout
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->tcs_out_offsets); // tcs out offsets
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->tcs_out_layout); // tcs out layout
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->tcs_in_layout); // tcs in layout
+ declare_global_input_sgprs(ctx, stage,
+ has_previous_stage,
+ previous_stage,
+ &user_sgpr_info, &args,
+ &desc_sets);
+
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->tcs_offchip_layout);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->tcs_out_offsets);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->tcs_out_layout);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->tcs_in_layout);
if (ctx->shader_info->info.needs_multiview_view_index)
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->view_index);
- add_sgpr_argument(&args, ctx->ac.i32, &ctx->oc_lds); // param oc lds
- add_sgpr_argument(&args, ctx->ac.i32, &ctx->tess_factor_offset); // tess factor offset
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->tcs_patch_id); // patch id
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->tcs_rel_ids); // rel ids;
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->view_index);
+
+ add_arg(&args, ARG_SGPR, ctx->ac.i32, &ctx->oc_lds);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->tess_factor_offset);
+ add_arg(&args, ARG_VGPR, ctx->ac.i32,
+ &ctx->abi.tcs_patch_id);
+ add_arg(&args, ARG_VGPR, ctx->ac.i32,
+ &ctx->abi.tcs_rel_ids);
}
break;
case MESA_SHADER_TESS_EVAL:
- radv_define_common_user_sgprs_phase1(ctx, stage, has_previous_stage, previous_stage, &user_sgpr_info, &args, &desc_sets);
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->tcs_offchip_layout); // tcs offchip layout
+ declare_global_input_sgprs(ctx, stage, has_previous_stage,
+ previous_stage, &user_sgpr_info,
+ &args, &desc_sets);
+
+ add_arg(&args, ARG_SGPR, ctx->ac.i32, &ctx->tcs_offchip_layout);
if (ctx->shader_info->info.needs_multiview_view_index || (!ctx->options->key.tes.as_es && ctx->options->key.has_multiview_view_index))
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->view_index);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32, &ctx->view_index);
+
if (ctx->options->key.tes.as_es) {
- add_sgpr_argument(&args, ctx->ac.i32, &ctx->oc_lds); // OC LDS
- add_sgpr_argument(&args, ctx->ac.i32, NULL); //
- add_sgpr_argument(&args, ctx->ac.i32, &ctx->es2gs_offset); // es2gs offset
+ add_arg(&args, ARG_SGPR, ctx->ac.i32, &ctx->oc_lds);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32, NULL);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->es2gs_offset);
} else {
- add_sgpr_argument(&args, ctx->ac.i32, NULL); //
- add_sgpr_argument(&args, ctx->ac.i32, &ctx->oc_lds); // OC LDS
+ add_arg(&args, ARG_SGPR, ctx->ac.i32, NULL);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32, &ctx->oc_lds);
}
- add_vgpr_argument(&args, ctx->ac.f32, &ctx->tes_u); // tes_u
- add_vgpr_argument(&args, ctx->ac.f32, &ctx->tes_v); // tes_v
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->tes_rel_patch_id); // tes rel patch id
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->tes_patch_id); // tes patch id
+ declare_tes_input_vgprs(ctx, &args);
break;
case MESA_SHADER_GEOMETRY:
if (has_previous_stage) {
// First 6 system regs
- add_sgpr_argument(&args, ctx->ac.i32, &ctx->gs2vs_offset); // tess factor offset
- add_sgpr_argument(&args, ctx->ac.i32, &ctx->merged_wave_info); // merged wave info
- add_sgpr_argument(&args, ctx->ac.i32, &ctx->oc_lds); // param oc lds
-
- add_sgpr_argument(&args, ctx->ac.i32, NULL); // scratch offset
- add_sgpr_argument(&args, ctx->ac.i32, NULL); // unknown
- add_sgpr_argument(&args, ctx->ac.i32, NULL); // unknown
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->gs2vs_offset);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->merged_wave_info);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32, &ctx->oc_lds);
+
+ add_arg(&args, ARG_SGPR, ctx->ac.i32, NULL); // scratch offset
+ add_arg(&args, ARG_SGPR, ctx->ac.i32, NULL); // unknown
+ add_arg(&args, ARG_SGPR, ctx->ac.i32, NULL); // unknown
+
+ declare_global_input_sgprs(ctx, stage,
+ has_previous_stage,
+ previous_stage,
+ &user_sgpr_info, &args,
+ &desc_sets);
+
+ if (previous_stage == MESA_SHADER_TESS_EVAL) {
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->tcs_offchip_layout);
+ } else {
+ declare_vs_specific_input_sgprs(ctx, stage,
+ has_previous_stage,
+ previous_stage,
+ &args);
+ }
- radv_define_common_user_sgprs_phase1(ctx, stage, has_previous_stage, previous_stage, &user_sgpr_info, &args, &desc_sets);
- if (previous_stage == MESA_SHADER_TESS_EVAL)
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->tcs_offchip_layout); // tcs offchip layout
- else
- radv_define_vs_user_sgprs_phase1(ctx, stage, has_previous_stage, previous_stage, &args);
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->gsvs_ring_stride); // gsvs stride
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->gsvs_num_entries); // gsvs num entires
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->gsvs_ring_stride);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->gsvs_num_entries);
if (ctx->shader_info->info.needs_multiview_view_index)
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->view_index);
-
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->gs_vtx_offset[0]); // vtx01
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->gs_vtx_offset[2]); // vtx23
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->abi.gs_prim_id); // prim id
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->abi.gs_invocation_id);
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->gs_vtx_offset[4]);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->view_index);
+
+ add_arg(&args, ARG_VGPR, ctx->ac.i32,
+ &ctx->gs_vtx_offset[0]);
+ add_arg(&args, ARG_VGPR, ctx->ac.i32,
+ &ctx->gs_vtx_offset[2]);
+ add_arg(&args, ARG_VGPR, ctx->ac.i32,
+ &ctx->abi.gs_prim_id);
+ add_arg(&args, ARG_VGPR, ctx->ac.i32,
+ &ctx->abi.gs_invocation_id);
+ add_arg(&args, ARG_VGPR, ctx->ac.i32,
+ &ctx->gs_vtx_offset[4]);
if (previous_stage == MESA_SHADER_VERTEX) {
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->abi.vertex_id); // vertex id
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->rel_auto_id); // rel auto id
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->vs_prim_id); // vs prim id
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->abi.instance_id); // instance id
+ declare_vs_input_vgprs(ctx, &args);
} else {
- add_vgpr_argument(&args, ctx->ac.f32, &ctx->tes_u); // tes_u
- add_vgpr_argument(&args, ctx->ac.f32, &ctx->tes_v); // tes_v
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->tes_rel_patch_id); // tes rel patch id
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->tes_patch_id); // tes patch id
+ declare_tes_input_vgprs(ctx, &args);
}
} else {
- radv_define_common_user_sgprs_phase1(ctx, stage, has_previous_stage, previous_stage, &user_sgpr_info, &args, &desc_sets);
- radv_define_vs_user_sgprs_phase1(ctx, stage, has_previous_stage, previous_stage, &args);
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->gsvs_ring_stride); // gsvs stride
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->gsvs_num_entries); // gsvs num entires
+ declare_global_input_sgprs(ctx, stage,
+ has_previous_stage,
+ previous_stage,
+ &user_sgpr_info, &args,
+ &desc_sets);
+
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->gsvs_ring_stride);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->gsvs_num_entries);
if (ctx->shader_info->info.needs_multiview_view_index)
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->view_index);
- add_sgpr_argument(&args, ctx->ac.i32, &ctx->gs2vs_offset); // gs2vs offset
- add_sgpr_argument(&args, ctx->ac.i32, &ctx->gs_wave_id); // wave id
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->gs_vtx_offset[0]); // vtx0
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->gs_vtx_offset[1]); // vtx1
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->abi.gs_prim_id); // prim id
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->gs_vtx_offset[2]);
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->gs_vtx_offset[3]);
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->gs_vtx_offset[4]);
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->gs_vtx_offset[5]);
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->abi.gs_invocation_id);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->view_index);
+
+ add_arg(&args, ARG_SGPR, ctx->ac.i32, &ctx->gs2vs_offset);
+ add_arg(&args, ARG_SGPR, ctx->ac.i32, &ctx->gs_wave_id);
+ add_arg(&args, ARG_VGPR, ctx->ac.i32,
+ &ctx->gs_vtx_offset[0]);
+ add_arg(&args, ARG_VGPR, ctx->ac.i32,
+ &ctx->gs_vtx_offset[1]);
+ add_arg(&args, ARG_VGPR, ctx->ac.i32,
+ &ctx->abi.gs_prim_id);
+ add_arg(&args, ARG_VGPR, ctx->ac.i32,
+ &ctx->gs_vtx_offset[2]);
+ add_arg(&args, ARG_VGPR, ctx->ac.i32,
+ &ctx->gs_vtx_offset[3]);
+ add_arg(&args, ARG_VGPR, ctx->ac.i32,
+ &ctx->gs_vtx_offset[4]);
+ add_arg(&args, ARG_VGPR, ctx->ac.i32,
+ &ctx->gs_vtx_offset[5]);
+ add_arg(&args, ARG_VGPR, ctx->ac.i32,
+ &ctx->abi.gs_invocation_id);
}
break;
case MESA_SHADER_FRAGMENT:
- radv_define_common_user_sgprs_phase1(ctx, stage, has_previous_stage, previous_stage, &user_sgpr_info, &args, &desc_sets);
+ declare_global_input_sgprs(ctx, stage, has_previous_stage,
+ previous_stage, &user_sgpr_info,
+ &args, &desc_sets);
+
if (ctx->shader_info->info.ps.needs_sample_positions)
- add_user_sgpr_argument(&args, ctx->ac.i32, &ctx->sample_pos_offset); /* sample position offset */
- add_sgpr_argument(&args, ctx->ac.i32, &ctx->prim_mask); /* prim mask */
- add_vgpr_argument(&args, ctx->ac.v2i32, &ctx->persp_sample); /* persp sample */
- add_vgpr_argument(&args, ctx->ac.v2i32, &ctx->persp_center); /* persp center */
- add_vgpr_argument(&args, ctx->ac.v2i32, &ctx->persp_centroid); /* persp centroid */
- add_vgpr_argument(&args, ctx->ac.v3i32, NULL); /* persp pull model */
- add_vgpr_argument(&args, ctx->ac.v2i32, &ctx->linear_sample); /* linear sample */
- add_vgpr_argument(&args, ctx->ac.v2i32, &ctx->linear_center); /* linear center */
- add_vgpr_argument(&args, ctx->ac.v2i32, &ctx->linear_centroid); /* linear centroid */
- add_vgpr_argument(&args, ctx->ac.f32, NULL); /* line stipple tex */
- add_vgpr_argument(&args, ctx->ac.f32, &ctx->abi.frag_pos[0]); /* pos x float */
- add_vgpr_argument(&args, ctx->ac.f32, &ctx->abi.frag_pos[1]); /* pos y float */
- add_vgpr_argument(&args, ctx->ac.f32, &ctx->abi.frag_pos[2]); /* pos z float */
- add_vgpr_argument(&args, ctx->ac.f32, &ctx->abi.frag_pos[3]); /* pos w float */
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->abi.front_face); /* front face */
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->abi.ancillary); /* ancillary */
- add_vgpr_argument(&args, ctx->ac.i32, &ctx->abi.sample_coverage); /* sample coverage */
- add_vgpr_argument(&args, ctx->ac.i32, NULL); /* fixed pt */
+ add_arg(&args, ARG_SGPR, ctx->ac.i32,
+ &ctx->sample_pos_offset);
+
+ add_arg(&args, ARG_SGPR, ctx->ac.i32, &ctx->prim_mask);
+ add_arg(&args, ARG_VGPR, ctx->ac.v2i32, &ctx->persp_sample);
+ add_arg(&args, ARG_VGPR, ctx->ac.v2i32, &ctx->persp_center);
+ add_arg(&args, ARG_VGPR, ctx->ac.v2i32, &ctx->persp_centroid);
+ add_arg(&args, ARG_VGPR, ctx->ac.v3i32, NULL); /* persp pull model */
+ add_arg(&args, ARG_VGPR, ctx->ac.v2i32, &ctx->linear_sample);
+ add_arg(&args, ARG_VGPR, ctx->ac.v2i32, &ctx->linear_center);
+ add_arg(&args, ARG_VGPR, ctx->ac.v2i32, &ctx->linear_centroid);
+ add_arg(&args, ARG_VGPR, ctx->ac.f32, NULL); /* line stipple tex */
+ add_arg(&args, ARG_VGPR, ctx->ac.f32, &ctx->abi.frag_pos[0]);
+ add_arg(&args, ARG_VGPR, ctx->ac.f32, &ctx->abi.frag_pos[1]);
+ add_arg(&args, ARG_VGPR, ctx->ac.f32, &ctx->abi.frag_pos[2]);
+ add_arg(&args, ARG_VGPR, ctx->ac.f32, &ctx->abi.frag_pos[3]);
+ add_arg(&args, ARG_VGPR, ctx->ac.i32, &ctx->abi.front_face);
+ add_arg(&args, ARG_VGPR, ctx->ac.i32, &ctx->abi.ancillary);
+ add_arg(&args, ARG_VGPR, ctx->ac.i32, &ctx->abi.sample_coverage);
+ add_arg(&args, ARG_VGPR, ctx->ac.i32, NULL); /* fixed pt */
break;
default:
unreachable("Shader stage not implemented");
user_sgpr_idx = 0;
if (ctx->options->supports_spill || user_sgpr_info.need_ring_offsets) {
- set_userdata_location_shader(ctx, AC_UD_SCRATCH_RING_OFFSETS, &user_sgpr_idx, 2);
+ set_loc_shader(ctx, AC_UD_SCRATCH_RING_OFFSETS,
+ &user_sgpr_idx, 2);
if (ctx->options->supports_spill) {
ctx->ring_offsets = ac_build_intrinsic(&ctx->ac, "llvm.amdgcn.implicit.buffer.ptr",
LLVMPointerType(ctx->ac.i8, CONST_ADDR_SPACE),
if (has_previous_stage)
user_sgpr_idx = 0;
- radv_define_common_user_sgprs_phase2(ctx, stage, has_previous_stage, previous_stage, &user_sgpr_info, desc_sets, &user_sgpr_idx);
+ set_global_input_locs(ctx, stage, has_previous_stage, previous_stage,
+ &user_sgpr_info, desc_sets, &user_sgpr_idx);
switch (stage) {
case MESA_SHADER_COMPUTE:
if (ctx->shader_info->info.cs.uses_grid_size) {
- set_userdata_location_shader(ctx, AC_UD_CS_GRID_SIZE,
- &user_sgpr_idx, 3);
+ set_loc_shader(ctx, AC_UD_CS_GRID_SIZE,
+ &user_sgpr_idx, 3);
}
break;
case MESA_SHADER_VERTEX:
- radv_define_vs_user_sgprs_phase2(ctx, stage, has_previous_stage, previous_stage, &user_sgpr_idx);
+ set_vs_specific_input_locs(ctx, stage, has_previous_stage,
+ previous_stage, &user_sgpr_idx);
if (ctx->view_index)
- set_userdata_location_shader(ctx, AC_UD_VIEW_INDEX, &user_sgpr_idx, 1);
+ set_loc_shader(ctx, AC_UD_VIEW_INDEX, &user_sgpr_idx, 1);
if (ctx->options->key.vs.as_ls) {
- set_userdata_location_shader(ctx, AC_UD_VS_LS_TCS_IN_LAYOUT, &user_sgpr_idx, 1);
+ set_loc_shader(ctx, AC_UD_VS_LS_TCS_IN_LAYOUT,
+ &user_sgpr_idx, 1);
}
if (ctx->options->key.vs.as_ls)
ac_declare_lds_as_pointer(&ctx->ac);
break;
case MESA_SHADER_TESS_CTRL:
- radv_define_vs_user_sgprs_phase2(ctx, stage, has_previous_stage, previous_stage, &user_sgpr_idx);
+ set_vs_specific_input_locs(ctx, stage, has_previous_stage,
+ previous_stage, &user_sgpr_idx);
if (has_previous_stage)
- set_userdata_location_shader(ctx, AC_UD_VS_LS_TCS_IN_LAYOUT, &user_sgpr_idx, 1);
- set_userdata_location_shader(ctx, AC_UD_TCS_OFFCHIP_LAYOUT, &user_sgpr_idx, 4);
+ set_loc_shader(ctx, AC_UD_VS_LS_TCS_IN_LAYOUT,
+ &user_sgpr_idx, 1);
+ set_loc_shader(ctx, AC_UD_TCS_OFFCHIP_LAYOUT, &user_sgpr_idx, 4);
if (ctx->view_index)
- set_userdata_location_shader(ctx, AC_UD_VIEW_INDEX, &user_sgpr_idx, 1);
+ set_loc_shader(ctx, AC_UD_VIEW_INDEX, &user_sgpr_idx, 1);
ac_declare_lds_as_pointer(&ctx->ac);
break;
case MESA_SHADER_TESS_EVAL:
- set_userdata_location_shader(ctx, AC_UD_TES_OFFCHIP_LAYOUT, &user_sgpr_idx, 1);
+ set_loc_shader(ctx, AC_UD_TES_OFFCHIP_LAYOUT, &user_sgpr_idx, 1);
if (ctx->view_index)
- set_userdata_location_shader(ctx, AC_UD_VIEW_INDEX, &user_sgpr_idx, 1);
+ set_loc_shader(ctx, AC_UD_VIEW_INDEX, &user_sgpr_idx, 1);
break;
case MESA_SHADER_GEOMETRY:
if (has_previous_stage) {
if (previous_stage == MESA_SHADER_VERTEX)
- radv_define_vs_user_sgprs_phase2(ctx, stage, has_previous_stage, previous_stage, &user_sgpr_idx);
+ set_vs_specific_input_locs(ctx, stage,
+ has_previous_stage,
+ previous_stage,
+ &user_sgpr_idx);
else
- set_userdata_location_shader(ctx, AC_UD_TES_OFFCHIP_LAYOUT, &user_sgpr_idx, 1);
+ set_loc_shader(ctx, AC_UD_TES_OFFCHIP_LAYOUT,
+ &user_sgpr_idx, 1);
}
- set_userdata_location_shader(ctx, AC_UD_GS_VS_RING_STRIDE_ENTRIES, &user_sgpr_idx, 2);
+ set_loc_shader(ctx, AC_UD_GS_VS_RING_STRIDE_ENTRIES,
+ &user_sgpr_idx, 2);
if (ctx->view_index)
- set_userdata_location_shader(ctx, AC_UD_VIEW_INDEX, &user_sgpr_idx, 1);
+ set_loc_shader(ctx, AC_UD_VIEW_INDEX, &user_sgpr_idx, 1);
if (has_previous_stage)
ac_declare_lds_as_pointer(&ctx->ac);
break;
case MESA_SHADER_FRAGMENT:
if (ctx->shader_info->info.ps.needs_sample_positions) {
- set_userdata_location_shader(ctx, AC_UD_PS_SAMPLE_POS_OFFSET, &user_sgpr_idx, 1);
+ set_loc_shader(ctx, AC_UD_PS_SAMPLE_POS_OFFSET,
+ &user_sgpr_idx, 1);
}
break;
default:
ctx->shader_info->num_user_sgprs = user_sgpr_idx;
}
-static int get_llvm_num_components(LLVMValueRef value)
-{
- LLVMTypeRef type = LLVMTypeOf(value);
- unsigned num_components = LLVMGetTypeKind(type) == LLVMVectorTypeKind
- ? LLVMGetVectorSize(type)
- : 1;
- return num_components;
-}
-
-static LLVMValueRef llvm_extract_elem(struct ac_llvm_context *ac,
- LLVMValueRef value,
- int index)
-{
- int count = get_llvm_num_components(value);
-
- if (count == 1)
- return value;
-
- return LLVMBuildExtractElement(ac->builder, value,
- LLVMConstInt(ac->i32, index, false), "");
-}
-
static LLVMValueRef trim_vector(struct ac_llvm_context *ctx,
LLVMValueRef value, unsigned count)
{
- unsigned num_components = get_llvm_num_components(value);
+ unsigned num_components = ac_get_llvm_num_components(value);
if (count == num_components)
return value;
}
static LLVMValueRef emit_fsign(struct ac_llvm_context *ctx,
- LLVMValueRef src0)
+ LLVMValueRef src0,
+ unsigned bitsize)
{
- LLVMValueRef cmp, val;
+ LLVMValueRef cmp, val, zero, one;
+ LLVMTypeRef type;
+
+ if (bitsize == 32) {
+ type = ctx->f32;
+ zero = ctx->f32_0;
+ one = ctx->f32_1;
+ } else {
+ type = ctx->f64;
+ zero = ctx->f64_0;
+ one = ctx->f64_1;
+ }
- cmp = LLVMBuildFCmp(ctx->builder, LLVMRealOGT, src0, ctx->f32_0, "");
- val = LLVMBuildSelect(ctx->builder, cmp, ctx->f32_1, src0, "");
- cmp = LLVMBuildFCmp(ctx->builder, LLVMRealOGE, val, ctx->f32_0, "");
- val = LLVMBuildSelect(ctx->builder, cmp, val, LLVMConstReal(ctx->f32, -1.0), "");
+ cmp = LLVMBuildFCmp(ctx->builder, LLVMRealOGT, src0, zero, "");
+ val = LLVMBuildSelect(ctx->builder, cmp, one, src0, "");
+ cmp = LLVMBuildFCmp(ctx->builder, LLVMRealOGE, val, zero, "");
+ val = LLVMBuildSelect(ctx->builder, cmp, val, LLVMConstReal(type, -1.0), "");
return val;
}
static LLVMValueRef emit_isign(struct ac_llvm_context *ctx,
- LLVMValueRef src0)
+ LLVMValueRef src0, unsigned bitsize)
{
- LLVMValueRef cmp, val;
+ LLVMValueRef cmp, val, zero, one;
+ LLVMTypeRef type;
+
+ if (bitsize == 32) {
+ type = ctx->i32;
+ zero = ctx->i32_0;
+ one = ctx->i32_1;
+ } else {
+ type = ctx->i64;
+ zero = ctx->i64_0;
+ one = ctx->i64_1;
+ }
- cmp = LLVMBuildICmp(ctx->builder, LLVMIntSGT, src0, ctx->i32_0, "");
- val = LLVMBuildSelect(ctx->builder, cmp, ctx->i32_1, src0, "");
- cmp = LLVMBuildICmp(ctx->builder, LLVMIntSGE, val, ctx->i32_0, "");
- val = LLVMBuildSelect(ctx->builder, cmp, val, LLVMConstInt(ctx->i32, -1, true), "");
+ cmp = LLVMBuildICmp(ctx->builder, LLVMIntSGT, src0, zero, "");
+ val = LLVMBuildSelect(ctx->builder, cmp, one, src0, "");
+ cmp = LLVMBuildICmp(ctx->builder, LLVMIntSGE, val, zero, "");
+ val = LLVMBuildSelect(ctx->builder, cmp, val, LLVMConstInt(type, -1, true), "");
return val;
}
}
static LLVMValueRef emit_b2i(struct ac_llvm_context *ctx,
- LLVMValueRef src0)
+ LLVMValueRef src0,
+ unsigned bitsize)
{
- return LLVMBuildAnd(ctx->builder, src0, ctx->i32_1, "");
+ LLVMValueRef result = LLVMBuildAnd(ctx->builder, src0, ctx->i32_1, "");
+
+ if (bitsize == 32)
+ return result;
+
+ return LLVMBuildZExt(ctx->builder, result, ctx->i64, "");
}
static LLVMValueRef emit_i2b(struct ac_llvm_context *ctx,
break;
case nir_op_frcp:
src[0] = ac_to_float(&ctx->ac, src[0]);
- result = ac_build_fdiv(&ctx->ac, ctx->ac.f32_1, src[0]);
+ result = ac_build_fdiv(&ctx->ac, instr->dest.dest.ssa.bit_size == 32 ? ctx->ac.f32_1 : ctx->ac.f64_1,
+ src[0]);
break;
case nir_op_iand:
result = LLVMBuildAnd(ctx->ac.builder, src[0], src[1], "");
result = emit_minmax_int(&ctx->ac, LLVMIntULT, src[0], src[1]);
break;
case nir_op_isign:
- result = emit_isign(&ctx->ac, src[0]);
+ result = emit_isign(&ctx->ac, src[0], instr->dest.dest.ssa.bit_size);
break;
case nir_op_fsign:
src[0] = ac_to_float(&ctx->ac, src[0]);
- result = emit_fsign(&ctx->ac, src[0]);
+ result = emit_fsign(&ctx->ac, src[0], instr->dest.dest.ssa.bit_size);
break;
case nir_op_ffloor:
result = emit_intrin_1f_param(&ctx->ac, "llvm.floor",
case nir_op_frsq:
result = emit_intrin_1f_param(&ctx->ac, "llvm.sqrt",
ac_to_float_type(&ctx->ac, def_type), src[0]);
- result = ac_build_fdiv(&ctx->ac, ctx->ac.f32_1, result);
+ result = ac_build_fdiv(&ctx->ac, instr->dest.dest.ssa.bit_size == 32 ? ctx->ac.f32_1 : ctx->ac.f64_1,
+ result);
break;
case nir_op_fpow:
result = emit_intrin_2f_param(&ctx->ac, "llvm.pow",
result = emit_f2b(&ctx->ac, src[0]);
break;
case nir_op_b2i:
- result = emit_b2i(&ctx->ac, src[0]);
+ result = emit_b2i(&ctx->ac, src[0], instr->dest.dest.ssa.bit_size);
break;
case nir_op_i2b:
src[0] = ac_to_integer(&ctx->ac, src[0]);
case nir_texop_txf:
case nir_texop_txf_ms:
case nir_texop_samples_identical:
- args->opcode = instr->sampler_dim == GLSL_SAMPLER_DIM_MS ? ac_image_load : ac_image_load_mip;
+ args->opcode = lod_is_zero ||
+ instr->sampler_dim == GLSL_SAMPLER_DIM_MS ?
+ ac_image_load : ac_image_load_mip;
args->compare = false;
args->offset = false;
break;
} else {
assert(count == 1);
- if (get_llvm_num_components(base_data) > 1)
+ if (ac_get_llvm_num_components(base_data) > 1)
data = LLVMBuildExtractElement(ctx->ac.builder, base_data,
LLVMConstInt(ctx->ac.i32, start, false), "");
else
int arg_count = 0;
if (instr->intrinsic == nir_intrinsic_ssbo_atomic_comp_swap) {
- params[arg_count++] = llvm_extract_elem(&ctx->ac, get_src(ctx, instr->src[3]), 0);
+ params[arg_count++] = ac_llvm_extract_elem(&ctx->ac, get_src(ctx, instr->src[3]), 0);
}
- params[arg_count++] = llvm_extract_elem(&ctx->ac, get_src(ctx, instr->src[2]), 0);
+ params[arg_count++] = ac_llvm_extract_elem(&ctx->ac, get_src(ctx, instr->src[2]), 0);
params[arg_count++] = ctx->abi->load_ssbo(ctx->abi,
get_src(ctx, instr->src[0]),
true);
static LLVMValueRef visit_load_ubo_buffer(struct ac_nir_context *ctx,
const nir_intrinsic_instr *instr)
{
- LLVMValueRef results[8], ret;
+ LLVMValueRef ret;
LLVMValueRef rsrc = get_src(ctx, instr->src[0]);
LLVMValueRef offset = get_src(ctx, instr->src[1]);
int num_components = instr->num_components;
if (instr->dest.ssa.bit_size == 64)
num_components *= 2;
- for (unsigned i = 0; i < num_components; ++i) {
- LLVMValueRef params[] = {
- rsrc,
- LLVMBuildAdd(ctx->ac.builder, LLVMConstInt(ctx->ac.i32, 4 * i, 0),
- offset, "")
- };
- results[i] = ac_build_intrinsic(&ctx->ac, "llvm.SI.load.const.v4i32", ctx->ac.f32,
- params, 2,
- AC_FUNC_ATTR_READNONE |
- AC_FUNC_ATTR_LEGACY);
- }
-
-
- ret = ac_build_gather_values(&ctx->ac, results, num_components);
+ ret = ac_build_buffer_load(&ctx->ac, rsrc, num_components, NULL, offset,
+ NULL, 0, false, false, true, true);
+ ret = trim_vector(&ctx->ac, ret, num_components);
return LLVMBuildBitCast(ctx->ac.builder, ret,
get_def_type(ctx, &instr->dest.ssa), "");
}
}
static LLVMValueRef
-load_tcs_input(struct nir_to_llvm_context *ctx,
- nir_intrinsic_instr *instr)
+load_tcs_input(struct ac_shader_abi *abi,
+ LLVMValueRef vertex_index,
+ LLVMValueRef indir_index,
+ unsigned const_index,
+ unsigned location,
+ unsigned driver_location,
+ unsigned component,
+ unsigned num_components,
+ bool is_patch,
+ bool is_compact)
{
+ struct nir_to_llvm_context *ctx = nir_to_llvm_context_from_abi(abi);
LLVMValueRef dw_addr, stride;
- unsigned const_index;
- LLVMValueRef vertex_index;
- LLVMValueRef indir_index;
- unsigned param;
LLVMValueRef value[4], result;
- const bool per_vertex = nir_is_per_vertex_io(instr->variables[0]->var, ctx->stage);
- const bool is_compact = instr->variables[0]->var->data.compact;
- param = shader_io_get_unique_index(instr->variables[0]->var->data.location);
- get_deref_offset(ctx->nir, instr->variables[0],
- false, NULL, per_vertex ? &vertex_index : NULL,
- &const_index, &indir_index);
+ unsigned param = shader_io_get_unique_index(location);
stride = unpack_param(&ctx->ac, ctx->tcs_in_layout, 13, 8);
dw_addr = get_tcs_in_current_patch_offset(ctx);
dw_addr = get_dw_address(ctx, dw_addr, param, const_index, is_compact, vertex_index, stride,
indir_index);
- unsigned comp = instr->variables[0]->var->data.location_frac;
- for (unsigned i = 0; i < instr->num_components + comp; i++) {
+ for (unsigned i = 0; i < num_components + component; i++) {
value[i] = ac_lds_load(&ctx->ac, dw_addr);
dw_addr = LLVMBuildAdd(ctx->builder, dw_addr,
ctx->ac.i32_1, "");
}
- result = ac_build_varying_gather_values(&ctx->ac, value, instr->num_components, comp);
- result = LLVMBuildBitCast(ctx->builder, result, get_def_type(ctx->nir, &instr->dest.ssa), "");
+ result = ac_build_varying_gather_values(&ctx->ac, value, num_components, component);
return result;
}
}
static void
-store_tcs_output(struct nir_to_llvm_context *ctx,
- nir_intrinsic_instr *instr,
+store_tcs_output(struct ac_shader_abi *abi,
+ LLVMValueRef vertex_index,
+ LLVMValueRef param_index,
+ unsigned const_index,
+ unsigned location,
+ unsigned driver_location,
LLVMValueRef src,
+ unsigned component,
+ bool is_patch,
+ bool is_compact,
unsigned writemask)
{
+ struct nir_to_llvm_context *ctx = nir_to_llvm_context_from_abi(abi);
LLVMValueRef dw_addr;
LLVMValueRef stride = NULL;
LLVMValueRef buf_addr = NULL;
- LLVMValueRef vertex_index = NULL;
- LLVMValueRef indir_index = NULL;
- unsigned const_index = 0;
unsigned param;
- const unsigned comp = instr->variables[0]->var->data.location_frac;
- const bool per_vertex = nir_is_per_vertex_io(instr->variables[0]->var, ctx->stage);
- const bool is_compact = instr->variables[0]->var->data.compact;
bool store_lds = true;
- if (instr->variables[0]->var->data.patch) {
- if (!(ctx->tcs_patch_outputs_read & (1U << instr->variables[0]->var->data.location)))
+ if (is_patch) {
+ if (!(ctx->tcs_patch_outputs_read & (1U << (location - VARYING_SLOT_PATCH0))))
store_lds = false;
} else {
- if (!(ctx->tcs_outputs_read & (1ULL << instr->variables[0]->var->data.location)))
+ if (!(ctx->tcs_outputs_read & (1ULL << location)))
store_lds = false;
}
- get_deref_offset(ctx->nir, instr->variables[0],
- false, NULL, per_vertex ? &vertex_index : NULL,
- &const_index, &indir_index);
- param = shader_io_get_unique_index(instr->variables[0]->var->data.location);
- if (instr->variables[0]->var->data.location == VARYING_SLOT_CLIP_DIST0 &&
+ param = shader_io_get_unique_index(location);
+ if (location == VARYING_SLOT_CLIP_DIST0 &&
is_compact && const_index > 3) {
const_index -= 3;
param++;
}
- if (!instr->variables[0]->var->data.patch) {
+ if (!is_patch) {
stride = unpack_param(&ctx->ac, ctx->tcs_out_layout, 13, 8);
dw_addr = get_tcs_out_current_patch_offset(ctx);
} else {
dw_addr = get_tcs_out_current_patch_data_offset(ctx);
}
- mark_tess_output(ctx, instr->variables[0]->var->data.patch, param);
+ mark_tess_output(ctx, is_patch, param);
dw_addr = get_dw_address(ctx, dw_addr, param, const_index, is_compact, vertex_index, stride,
- indir_index);
+ param_index);
buf_addr = get_tcs_tes_buffer_address_params(ctx, param, const_index, is_compact,
- vertex_index, indir_index);
+ vertex_index, param_index);
bool is_tess_factor = false;
- if (instr->variables[0]->var->data.location == VARYING_SLOT_TESS_LEVEL_INNER ||
- instr->variables[0]->var->data.location == VARYING_SLOT_TESS_LEVEL_OUTER)
+ if (location == VARYING_SLOT_TESS_LEVEL_INNER ||
+ location == VARYING_SLOT_TESS_LEVEL_OUTER)
is_tess_factor = true;
unsigned base = is_compact ? const_index : 0;
for (unsigned chan = 0; chan < 8; chan++) {
if (!(writemask & (1 << chan)))
continue;
- LLVMValueRef value = llvm_extract_elem(&ctx->ac, src, chan - comp);
+ LLVMValueRef value = ac_llvm_extract_elem(&ctx->ac, src, chan - component);
if (store_lds || is_tess_factor)
ac_lds_store(&ctx->ac, dw_addr, value);
}
static LLVMValueRef
-load_tes_input(struct nir_to_llvm_context *ctx,
- const nir_intrinsic_instr *instr)
+load_tes_input(struct ac_shader_abi *abi,
+ LLVMValueRef vertex_index,
+ LLVMValueRef param_index,
+ unsigned const_index,
+ unsigned location,
+ unsigned driver_location,
+ unsigned component,
+ unsigned num_components,
+ bool is_patch,
+ bool is_compact)
{
+ struct nir_to_llvm_context *ctx = nir_to_llvm_context_from_abi(abi);
LLVMValueRef buf_addr;
LLVMValueRef result;
- LLVMValueRef vertex_index = NULL;
- LLVMValueRef indir_index = NULL;
- unsigned const_index = 0;
- unsigned param;
- const bool per_vertex = nir_is_per_vertex_io(instr->variables[0]->var, ctx->stage);
- const bool is_compact = instr->variables[0]->var->data.compact;
+ unsigned param = shader_io_get_unique_index(location);
- get_deref_offset(ctx->nir, instr->variables[0],
- false, NULL, per_vertex ? &vertex_index : NULL,
- &const_index, &indir_index);
- param = shader_io_get_unique_index(instr->variables[0]->var->data.location);
- if (instr->variables[0]->var->data.location == VARYING_SLOT_CLIP_DIST0 &&
- is_compact && const_index > 3) {
+ if (location == VARYING_SLOT_CLIP_DIST0 && is_compact && const_index > 3) {
const_index -= 3;
param++;
}
- unsigned comp = instr->variables[0]->var->data.location_frac;
buf_addr = get_tcs_tes_buffer_address_params(ctx, param, const_index,
- is_compact, vertex_index, indir_index);
+ is_compact, vertex_index, param_index);
- LLVMValueRef comp_offset = LLVMConstInt(ctx->ac.i32, comp * 4, false);
+ LLVMValueRef comp_offset = LLVMConstInt(ctx->ac.i32, component * 4, false);
buf_addr = LLVMBuildAdd(ctx->builder, buf_addr, comp_offset, "");
- result = ac_build_buffer_load(&ctx->ac, ctx->hs_ring_tess_offchip, instr->num_components, NULL,
+ result = ac_build_buffer_load(&ctx->ac, ctx->hs_ring_tess_offchip, num_components, NULL,
buf_addr, ctx->oc_lds, is_compact ? (4 * const_index) : 0, 1, 0, true, false);
- result = trim_vector(&ctx->ac, result, instr->num_components);
- result = LLVMBuildBitCast(ctx->builder, result, get_def_type(ctx->nir, &instr->dest.ssa), "");
+ result = trim_vector(&ctx->ac, result, num_components);
return result;
}
LLVMValueRef indir_index;
LLVMValueRef ret;
unsigned const_index;
+ unsigned stride = instr->variables[0]->var->data.compact ? 1 : 4;
bool vs_in = ctx->stage == MESA_SHADER_VERTEX &&
instr->variables[0]->var->data.mode == nir_var_shader_in;
get_deref_offset(ctx, instr->variables[0], vs_in, NULL, NULL,
switch (instr->variables[0]->var->data.mode) {
case nir_var_shader_in:
- if (ctx->stage == MESA_SHADER_TESS_CTRL)
- return load_tcs_input(ctx->nctx, instr);
- if (ctx->stage == MESA_SHADER_TESS_EVAL)
- return load_tes_input(ctx->nctx, instr);
+ if (ctx->stage == MESA_SHADER_TESS_CTRL ||
+ ctx->stage == MESA_SHADER_TESS_EVAL) {
+ LLVMValueRef result;
+ LLVMValueRef vertex_index = NULL;
+ LLVMValueRef indir_index = NULL;
+ unsigned const_index = 0;
+ unsigned location = instr->variables[0]->var->data.location;
+ unsigned driver_location = instr->variables[0]->var->data.driver_location;
+ const bool is_patch = instr->variables[0]->var->data.patch;
+ const bool is_compact = instr->variables[0]->var->data.compact;
+
+ get_deref_offset(ctx, instr->variables[0],
+ false, NULL, is_patch ? NULL : &vertex_index,
+ &const_index, &indir_index);
+
+ result = ctx->abi->load_tess_inputs(ctx->abi, vertex_index, indir_index,
+ const_index, location, driver_location,
+ instr->variables[0]->var->data.location_frac,
+ instr->num_components,
+ is_patch, is_compact);
+ return LLVMBuildBitCast(ctx->ac.builder, result, get_def_type(ctx, &instr->dest.ssa), "");
+ }
+
if (ctx->stage == MESA_SHADER_GEOMETRY) {
LLVMValueRef indir_index;
unsigned const_index, vertex_index;
count -= chan / 4;
LLVMValueRef tmp_vec = ac_build_gather_values_extended(
&ctx->ac, ctx->abi->inputs + idx + chan, count,
- 4, false, true);
+ stride, false, true);
values[chan] = LLVMBuildExtractElement(ctx->ac.builder,
tmp_vec,
indir_index, "");
} else
- values[chan] = ctx->abi->inputs[idx + chan + const_index * 4];
+ values[chan] = ctx->abi->inputs[idx + chan + const_index * stride];
}
break;
case nir_var_local:
count -= chan / 4;
LLVMValueRef tmp_vec = ac_build_gather_values_extended(
&ctx->ac, ctx->locals + idx + chan, count,
- 4, true, true);
+ stride, true, true);
values[chan] = LLVMBuildExtractElement(ctx->ac.builder,
tmp_vec,
indir_index, "");
} else {
- values[chan] = LLVMBuildLoad(ctx->ac.builder, ctx->locals[idx + chan + const_index * 4], "");
+ values[chan] = LLVMBuildLoad(ctx->ac.builder, ctx->locals[idx + chan + const_index * stride], "");
}
}
break;
count -= chan / 4;
LLVMValueRef tmp_vec = ac_build_gather_values_extended(
&ctx->ac, ctx->outputs + idx + chan, count,
- 4, true, true);
+ stride, true, true);
values[chan] = LLVMBuildExtractElement(ctx->ac.builder,
tmp_vec,
indir_index, "");
} else {
values[chan] = LLVMBuildLoad(ctx->ac.builder,
- ctx->outputs[idx + chan + const_index * 4],
+ ctx->outputs[idx + chan + const_index * stride],
"");
}
}
int old_writemask = writemask;
src = LLVMBuildBitCast(ctx->ac.builder, src,
- LLVMVectorType(ctx->ac.f32, get_llvm_num_components(src) * 2),
+ LLVMVectorType(ctx->ac.f32, ac_get_llvm_num_components(src) * 2),
"");
writemask = 0;
case nir_var_shader_out:
if (ctx->stage == MESA_SHADER_TESS_CTRL) {
- store_tcs_output(ctx->nctx, instr, src, writemask);
+ LLVMValueRef vertex_index = NULL;
+ LLVMValueRef indir_index = NULL;
+ unsigned const_index = 0;
+ const unsigned location = instr->variables[0]->var->data.location;
+ const unsigned driver_location = instr->variables[0]->var->data.driver_location;
+ const unsigned comp = instr->variables[0]->var->data.location_frac;
+ const bool is_patch = instr->variables[0]->var->data.patch;
+ const bool is_compact = instr->variables[0]->var->data.compact;
+
+ get_deref_offset(ctx, instr->variables[0],
+ false, NULL, is_patch ? NULL : &vertex_index,
+ &const_index, &indir_index);
+
+ ctx->abi->store_tcs_outputs(ctx->abi, vertex_index, indir_index,
+ const_index, location, driver_location,
+ src, comp, is_patch, is_compact, writemask);
return;
}
if (!(writemask & (1 << chan)))
continue;
- value = llvm_extract_elem(&ctx->ac, src, chan - comp);
+ value = ac_llvm_extract_elem(&ctx->ac, src, chan - comp);
if (instr->variables[0]->var->data.compact)
stride = 1;
if (!(writemask & (1 << chan)))
continue;
- value = llvm_extract_elem(&ctx->ac, src, chan);
+ value = ac_llvm_extract_elem(&ctx->ac, src, chan);
if (indir_index) {
unsigned count = glsl_count_attribute_slots(
instr->variables[0]->var->type, false);
LLVMValueRef ptr =
LLVMBuildStructGEP(ctx->ac.builder,
address, chan, "");
- LLVMValueRef src = llvm_extract_elem(&ctx->ac, val,
- chan);
+ LLVMValueRef src = ac_llvm_extract_elem(&ctx->ac, val,
+ chan);
src = LLVMBuildBitCast(
ctx->ac.builder, src,
LLVMGetElementType(LLVMTypeOf(ptr)), "");
LLVMConstInt(ctx->ac.i32, 2, false), LLVMConstInt(ctx->ac.i32, 3, false),
};
LLVMValueRef res;
- LLVMValueRef sample_index = llvm_extract_elem(&ctx->ac, get_src(ctx, instr->src[1]), 0);
+ LLVMValueRef sample_index = ac_llvm_extract_elem(&ctx->ac, get_src(ctx, instr->src[1]), 0);
int count;
enum glsl_sampler_dim dim = glsl_get_sampler_dim(type);
if (is_ms)
count--;
for (chan = 0; chan < count; ++chan) {
- coords[chan] = llvm_extract_elem(&ctx->ac, src0, chan);
+ coords[chan] = ac_llvm_extract_elem(&ctx->ac, src0, chan);
}
if (add_frag_pos) {
for (chan = 0; chan < 2; ++chan)
#define LGKM_CNT 0x07f
#define VM_CNT 0xf70
-static void emit_waitcnt(struct nir_to_llvm_context *ctx,
- unsigned simm16)
-{
- LLVMValueRef args[1] = {
- LLVMConstInt(ctx->ac.i32, simm16, false),
- };
- ac_build_intrinsic(&ctx->ac, "llvm.amdgcn.s.waitcnt",
- ctx->ac.voidt, args, 1, 0);
-}
-
static void emit_membar(struct nir_to_llvm_context *ctx,
const nir_intrinsic_instr *instr)
{
break;
}
if (waitcnt != NOOP_WAITCNT)
- emit_waitcnt(ctx, waitcnt);
+ ac_build_waitcnt(&ctx->ac, waitcnt);
}
-static void emit_barrier(struct nir_to_llvm_context *ctx)
+static void emit_barrier(struct ac_llvm_context *ac, gl_shader_stage stage)
{
/* SI only (thanks to a hw bug workaround):
* The real barrier instruction isn’t needed, because an entire patch
* always fits into a single wave.
*/
- if (ctx->options->chip_class == SI &&
- ctx->stage == MESA_SHADER_TESS_CTRL) {
- emit_waitcnt(ctx, LGKM_CNT & VM_CNT);
+ if (ac->chip_class == SI && stage == MESA_SHADER_TESS_CTRL) {
+ ac_build_waitcnt(ac, LGKM_CNT & VM_CNT);
return;
}
- ac_build_intrinsic(&ctx->ac, "llvm.amdgcn.s.barrier",
- ctx->ac.voidt, NULL, 0, AC_FUNC_ATTR_CONVERGENT);
+ ac_build_intrinsic(ac, "llvm.amdgcn.s.barrier",
+ ac->voidt, NULL, 0, AC_FUNC_ATTR_CONVERGENT);
}
static void emit_discard_if(struct ac_nir_context *ctx,
}
static LLVMValueRef
-visit_load_tess_coord(struct nir_to_llvm_context *ctx,
- const nir_intrinsic_instr *instr)
+load_tess_coord(struct ac_shader_abi *abi, LLVMTypeRef type,
+ unsigned num_components)
{
+ struct nir_to_llvm_context *ctx = nir_to_llvm_context_from_abi(abi);
+
LLVMValueRef coord[4] = {
ctx->tes_u,
ctx->tes_v,
coord[2] = LLVMBuildFSub(ctx->builder, ctx->ac.f32_1,
LLVMBuildFAdd(ctx->builder, coord[0], coord[1], ""), "");
- LLVMValueRef result = ac_build_gather_values(&ctx->ac, coord, instr->num_components);
- return LLVMBuildBitCast(ctx->builder, result,
- get_def_type(ctx->nir, &instr->dest.ssa), "");
+ LLVMValueRef result = ac_build_gather_values(&ctx->ac, coord, num_components);
+ return LLVMBuildBitCast(ctx->builder, result, type, "");
+}
+
+static LLVMValueRef
+load_patch_vertices_in(struct ac_shader_abi *abi)
+{
+ struct nir_to_llvm_context *ctx = nir_to_llvm_context_from_abi(abi);
+ return LLVMConstInt(ctx->ac.i32, ctx->options->key.tcs.input_vertices, false);
}
static void visit_intrinsic(struct ac_nir_context *ctx,
switch (instr->intrinsic) {
case nir_intrinsic_load_work_group_id: {
- result = ctx->nctx->workgroup_ids;
+ LLVMValueRef values[3];
+
+ for (int i = 0; i < 3; i++) {
+ values[i] = ctx->nctx->workgroup_ids[i] ?
+ ctx->nctx->workgroup_ids[i] : ctx->ac.i32_0;
+ }
+
+ result = ac_build_gather_values(&ctx->ac, values, 3);
break;
}
case nir_intrinsic_load_base_vertex: {
break;
case nir_intrinsic_load_invocation_id:
if (ctx->stage == MESA_SHADER_TESS_CTRL)
- result = unpack_param(&ctx->ac, ctx->nctx->tcs_rel_ids, 8, 5);
+ result = unpack_param(&ctx->ac, ctx->abi->tcs_rel_ids, 8, 5);
else
result = ctx->abi->gs_invocation_id;
break;
case nir_intrinsic_load_primitive_id:
if (ctx->stage == MESA_SHADER_GEOMETRY) {
- if (ctx->nctx)
- ctx->nctx->shader_info->gs.uses_prim_id = true;
result = ctx->abi->gs_prim_id;
} else if (ctx->stage == MESA_SHADER_TESS_CTRL) {
- ctx->nctx->shader_info->tcs.uses_prim_id = true;
- result = ctx->nctx->tcs_patch_id;
+ result = ctx->abi->tcs_patch_id;
} else if (ctx->stage == MESA_SHADER_TESS_EVAL) {
- ctx->nctx->shader_info->tcs.uses_prim_id = true;
- result = ctx->nctx->tes_patch_id;
+ result = ctx->abi->tes_patch_id;
} else
fprintf(stderr, "Unknown primitive id intrinsic: %d", ctx->stage);
break;
emit_membar(ctx->nctx, instr);
break;
case nir_intrinsic_barrier:
- emit_barrier(ctx->nctx);
+ emit_barrier(&ctx->ac, ctx->stage);
break;
case nir_intrinsic_var_atomic_add:
case nir_intrinsic_var_atomic_imin:
case nir_intrinsic_end_primitive:
visit_end_primitive(ctx->nctx, instr);
break;
- case nir_intrinsic_load_tess_coord:
- result = visit_load_tess_coord(ctx->nctx, instr);
+ case nir_intrinsic_load_tess_coord: {
+ LLVMTypeRef type = ctx->nctx ?
+ get_def_type(ctx->nctx->nir, &instr->dest.ssa) :
+ NULL;
+ result = ctx->abi->load_tess_coord(ctx->abi, type, instr->num_components);
+ break;
+ }
+ case nir_intrinsic_load_tess_level_outer:
+ result = ctx->abi->load_tess_level(ctx->abi, VARYING_SLOT_TESS_LEVEL_OUTER);
+ break;
+ case nir_intrinsic_load_tess_level_inner:
+ result = ctx->abi->load_tess_level(ctx->abi, VARYING_SLOT_TESS_LEVEL_INNER);
break;
case nir_intrinsic_load_patch_vertices_in:
- result = LLVMConstInt(ctx->ac.i32, ctx->nctx->options->key.tcs.input_vertices, false);
+ result = ctx->abi->load_patch_vertices_in(ctx->abi);
break;
default:
fprintf(stderr, "Unknown intrinsic: ");
if (coord)
for (chan = 0; chan < instr->coord_components; chan++)
- coords[chan] = llvm_extract_elem(&ctx->ac, coord, chan);
+ coords[chan] = ac_llvm_extract_elem(&ctx->ac, coord, chan);
if (offsets && instr->op != nir_texop_txf) {
LLVMValueRef offset[3], pack;
offset[chan] = ctx->ac.i32_0;
args.offset = true;
- for (chan = 0; chan < get_llvm_num_components(offsets); chan++) {
- offset[chan] = llvm_extract_elem(&ctx->ac, offsets, chan);
+ for (chan = 0; chan < ac_get_llvm_num_components(offsets); chan++) {
+ offset[chan] = ac_llvm_extract_elem(&ctx->ac, offsets, chan);
offset[chan] = LLVMBuildAnd(ctx->ac.builder, offset[chan],
LLVMConstInt(ctx->ac.i32, 0x3f, false), "");
if (chan)
/* Pack depth comparison value */
if (instr->is_shadow && comparator) {
LLVMValueRef z = ac_to_float(&ctx->ac,
- llvm_extract_elem(&ctx->ac, comparator, 0));
+ ac_llvm_extract_elem(&ctx->ac, comparator, 0));
/* TC-compatible HTILE on radeonsi promotes Z16 and Z24 to Z32_FLOAT,
* so the depth comparison value isn't clamped for Z16 and
}
for (unsigned i = 0; i < num_src_deriv_channels; i++) {
- derivs[i] = ac_to_float(&ctx->ac, llvm_extract_elem(&ctx->ac, ddx, i));
- derivs[num_dest_deriv_channels + i] = ac_to_float(&ctx->ac, llvm_extract_elem(&ctx->ac, ddy, i));
+ derivs[i] = ac_to_float(&ctx->ac, ac_llvm_extract_elem(&ctx->ac, ddx, i));
+ derivs[num_dest_deriv_channels + i] = ac_to_float(&ctx->ac, ac_llvm_extract_elem(&ctx->ac, ddy, i));
}
for (unsigned i = num_src_deriv_channels; i < num_dest_deriv_channels; i++) {
derivs[i] = ctx->ac.f32_0;
if (ctx->options->key.vs.instance_rate_inputs & (1u << index)) {
buffer_index = LLVMBuildAdd(ctx->builder, ctx->abi.instance_id,
ctx->abi.start_instance, "");
- ctx->shader_info->vs.vgpr_comp_cnt = MAX2(3,
- ctx->shader_info->vs.vgpr_comp_cnt);
+ if (ctx->options->key.vs.as_ls) {
+ ctx->shader_info->vs.vgpr_comp_cnt =
+ MAX2(2, ctx->shader_info->vs.vgpr_comp_cnt);
+ } else {
+ ctx->shader_info->vs.vgpr_comp_cnt =
+ MAX2(1, ctx->shader_info->vs.vgpr_comp_cnt);
+ }
} else
buffer_index = LLVMBuildAdd(ctx->builder, ctx->abi.vertex_id,
ctx->abi.base_vertex, "");
nir_foreach_variable(variable, &func->impl->locals) {
unsigned attrib_count = glsl_count_attribute_slots(variable->type, false);
variable->data.driver_location = ctx->num_locals * 4;
+ variable->data.location_frac = 0;
ctx->num_locals += attrib_count;
}
ctx->locals = malloc(4 * ctx->num_locals * sizeof(LLVMValueRef));
{
unsigned stride, outer_comps, inner_comps;
struct ac_build_if_state if_ctx, inner_if_ctx;
- LLVMValueRef invocation_id = unpack_param(&ctx->ac, ctx->tcs_rel_ids, 8, 5);
- LLVMValueRef rel_patch_id = unpack_param(&ctx->ac, ctx->tcs_rel_ids, 0, 8);
+ LLVMValueRef invocation_id = unpack_param(&ctx->ac, ctx->abi.tcs_rel_ids, 8, 5);
+ LLVMValueRef rel_patch_id = unpack_param(&ctx->ac, ctx->abi.tcs_rel_ids, 0, 8);
unsigned tess_inner_index, tess_outer_index;
LLVMValueRef lds_base, lds_inner, lds_outer, byteoffset, buffer;
LLVMValueRef out[6], vec0, vec1, tf_base, inner[4], outer[4];
int i;
- emit_barrier(ctx);
+ emit_barrier(&ctx->ac, ctx->stage);
switch (ctx->options->key.tcs.primitive_mode) {
case GL_ISOLINES:
}
static void
-si_export_mrt_z(struct nir_to_llvm_context *ctx,
- LLVMValueRef depth, LLVMValueRef stencil,
- LLVMValueRef samplemask)
+radv_export_mrt_z(struct nir_to_llvm_context *ctx,
+ LLVMValueRef depth, LLVMValueRef stencil,
+ LLVMValueRef samplemask)
{
struct ac_export_args args;
- args.enabled_channels = 0;
- args.valid_mask = 1;
- args.done = 1;
- args.target = V_008DFC_SQ_EXP_MRTZ;
- args.compr = false;
-
- args.out[0] = LLVMGetUndef(ctx->ac.f32); /* R, depth */
- args.out[1] = LLVMGetUndef(ctx->ac.f32); /* G, stencil test val[0:7], stencil op val[8:15] */
- args.out[2] = LLVMGetUndef(ctx->ac.f32); /* B, sample mask */
- args.out[3] = LLVMGetUndef(ctx->ac.f32); /* A, alpha to mask */
-
- unsigned format = ac_get_spi_shader_z_format(depth != NULL,
- stencil != NULL,
- samplemask != NULL);
-
- if (format == V_028710_SPI_SHADER_UINT16_ABGR) {
- assert(!depth);
- args.compr = 1; /* COMPR flag */
-
- if (stencil) {
- /* Stencil should be in X[23:16]. */
- stencil = ac_to_integer(&ctx->ac, stencil);
- stencil = LLVMBuildShl(ctx->builder, stencil,
- LLVMConstInt(ctx->ac.i32, 16, 0), "");
- args.out[0] = ac_to_float(&ctx->ac, stencil);
- args.enabled_channels |= 0x3;
- }
- if (samplemask) {
- /* SampleMask should be in Y[15:0]. */
- args.out[1] = samplemask;
- args.enabled_channels |= 0xc;
- }
- } else {
- if (depth) {
- args.out[0] = depth;
- args.enabled_channels |= 0x1;
- }
-
- if (stencil) {
- args.out[1] = stencil;
- args.enabled_channels |= 0x2;
- }
-
- if (samplemask) {
- args.out[2] = samplemask;
- args.enabled_channels |= 0x4;
- }
- }
-
- /* SI (except OLAND and HAINAN) has a bug that it only looks
- * at the X writemask component. */
- if (ctx->options->chip_class == SI &&
- ctx->options->family != CHIP_OLAND &&
- ctx->options->family != CHIP_HAINAN)
- args.enabled_channels |= 0x1;
+ ac_export_mrt_z(&ctx->ac, depth, stencil, samplemask, &args);
ac_build_export(&ctx->ac, &args);
}
for (unsigned i = 0; i < index; i++)
ac_build_export(&ctx->ac, &color_args[i]);
if (depth || stencil || samplemask)
- si_export_mrt_z(ctx, depth, stencil, samplemask);
+ radv_export_mrt_z(ctx, depth, stencil, samplemask);
else if (!index) {
si_export_mrt_color(ctx, NULL, V_008DFC_SQ_EXP_NULL, true, &color_args[0]);
ac_build_export(&ctx->ac, &color_args[0]);
ctx->ac.i32_0, "");
ctx->abi.instance_id = LLVMBuildSelect(ctx->ac.builder, hs_empty, ctx->rel_auto_id, ctx->abi.instance_id, "");
ctx->vs_prim_id = LLVMBuildSelect(ctx->ac.builder, hs_empty, ctx->abi.vertex_id, ctx->vs_prim_id, "");
- ctx->rel_auto_id = LLVMBuildSelect(ctx->ac.builder, hs_empty, ctx->tcs_rel_ids, ctx->rel_auto_id, "");
- ctx->abi.vertex_id = LLVMBuildSelect(ctx->ac.builder, hs_empty, ctx->tcs_patch_id, ctx->abi.vertex_id, "");
+ ctx->rel_auto_id = LLVMBuildSelect(ctx->ac.builder, hs_empty, ctx->abi.tcs_rel_ids, ctx->rel_auto_id, "");
+ ctx->abi.vertex_id = LLVMBuildSelect(ctx->ac.builder, hs_empty, ctx->abi.tcs_patch_id, ctx->abi.vertex_id, "");
}
static void prepare_gs_input_vgprs(struct nir_to_llvm_context *ctx)
ctx.context = LLVMContextCreate();
ctx.module = LLVMModuleCreateWithNameInContext("shader", ctx.context);
- ac_llvm_context_init(&ctx.ac, ctx.context, options->chip_class);
+ ac_llvm_context_init(&ctx.ac, ctx.context, options->chip_class,
+ options->family);
ctx.ac.module = ctx.module;
LLVMSetTarget(ctx.module, options->supports_spill ? "amdgcn-mesa-mesa3d" : "amdgcn--");
} else if (shaders[i]->info.stage == MESA_SHADER_TESS_CTRL) {
ctx.tcs_outputs_read = shaders[i]->info.outputs_read;
ctx.tcs_patch_outputs_read = shaders[i]->info.patch_outputs_read;
+ ctx.abi.load_tess_inputs = load_tcs_input;
+ ctx.abi.load_patch_vertices_in = load_patch_vertices_in;
+ ctx.abi.store_tcs_outputs = store_tcs_output;
} else if (shaders[i]->info.stage == MESA_SHADER_TESS_EVAL) {
ctx.tes_primitive_mode = shaders[i]->info.tess.primitive_mode;
+ ctx.abi.load_tess_inputs = load_tes_input;
+ ctx.abi.load_tess_coord = load_tess_coord;
+ ctx.abi.load_patch_vertices_in = load_patch_vertices_in;
} else if (shaders[i]->info.stage == MESA_SHADER_VERTEX) {
if (shader_info->info.vs.needs_instance_id) {
- ctx.shader_info->vs.vgpr_comp_cnt =
- MAX2(3, ctx.shader_info->vs.vgpr_comp_cnt);
+ if (ctx.ac.chip_class == GFX9 &&
+ shaders[shader_count - 1]->info.stage == MESA_SHADER_TESS_CTRL) {
+ ctx.shader_info->vs.vgpr_comp_cnt =
+ MAX2(2, ctx.shader_info->vs.vgpr_comp_cnt);
+ } else {
+ ctx.shader_info->vs.vgpr_comp_cnt =
+ MAX2(1, ctx.shader_info->vs.vgpr_comp_cnt);
+ }
}
} else if (shaders[i]->info.stage == MESA_SHADER_FRAGMENT) {
shader_info->fs.can_discard = shaders[i]->info.fs.uses_discard;
}
if (i)
- emit_barrier(&ctx);
+ emit_barrier(&ctx.ac, ctx.stage);
ac_setup_rings(&ctx);
/* +3 for scratch wave offset and VCC */
config->num_sgprs = MAX2(config->num_sgprs,
shader_info->num_input_sgprs + 3);
+
+ /* Enable 64-bit and 16-bit denormals, because there is no performance
+ * cost.
+ *
+ * If denormals are enabled, all floating-point output modifiers are
+ * ignored.
+ *
+ * Don't enable denormals for 32-bit floats, because:
+ * - Floating-point output modifiers would be ignored by the hw.
+ * - Some opcodes don't support denormals, such as v_mad_f32. We would
+ * have to stop using those.
+ * - SI & CI would be very slow.
+ */
+ config->float_mode |= V_00B028_FP_64_DENORMS;
}
static void
case MESA_SHADER_VERTEX:
shader_info->vs.as_es = options->key.vs.as_es;
shader_info->vs.as_ls = options->key.vs.as_ls;
- /* in LS mode we need at least 1, invocation id needs 3, handled elsewhere */
+ /* in LS mode we need at least 1, invocation id needs 2, handled elsewhere */
if (options->key.vs.as_ls)
shader_info->vs.vgpr_comp_cnt = MAX2(1, shader_info->vs.vgpr_comp_cnt);
break;
ac_compile_llvm_module(tm, llvm_module, binary, config, shader_info, nir[0]->info.stage, dump_shader, options->supports_spill);
for (int i = 0; i < nir_count; ++i)
ac_fill_shader_info(shader_info, nir[i], options);
+
+ /* Determine the ES type (VS or TES) for the GS on GFX9. */
+ if (options->chip_class == GFX9) {
+ if (nir_count == 2 &&
+ nir[1]->info.stage == MESA_SHADER_GEOMETRY) {
+ shader_info->gs.es_type = nir[0]->info.stage;
+ }
+ }
}
static void
ctx.options = options;
ctx.shader_info = shader_info;
- ac_llvm_context_init(&ctx.ac, ctx.context, options->chip_class);
+ ac_llvm_context_init(&ctx.ac, ctx.context, options->chip_class,
+ options->family);
ctx.ac.module = ctx.module;
ctx.is_gs_copy_shader = true;