union si_shader_part_key *key);
static void si_build_vs_epilog_function(struct si_shader_context *ctx,
union si_shader_part_key *key);
+static void si_build_tcs_epilog_function(struct si_shader_context *ctx,
+ union si_shader_part_key *key);
static void si_build_ps_prolog_function(struct si_shader_context *ctx,
union si_shader_part_key *key);
static void si_build_ps_epilog_function(struct si_shader_context *ctx,
}
}
-/* This shouldn't be used by explicit INTERP opcodes. */
-static unsigned select_interp_param(struct si_shader_context *ctx,
- unsigned param)
-{
- if (!ctx->no_prolog)
- return param;
-
- if (ctx->shader->key.ps.prolog.force_persp_sample_interp) {
- switch (param) {
- case SI_PARAM_PERSP_CENTROID:
- case SI_PARAM_PERSP_CENTER:
- return SI_PARAM_PERSP_SAMPLE;
- }
- }
- if (ctx->shader->key.ps.prolog.force_linear_sample_interp) {
- switch (param) {
- case SI_PARAM_LINEAR_CENTROID:
- case SI_PARAM_LINEAR_CENTER:
- return SI_PARAM_LINEAR_SAMPLE;
- }
- }
- if (ctx->shader->key.ps.prolog.force_persp_center_interp) {
- switch (param) {
- case SI_PARAM_PERSP_CENTROID:
- case SI_PARAM_PERSP_SAMPLE:
- return SI_PARAM_PERSP_CENTER;
- }
- }
- if (ctx->shader->key.ps.prolog.force_linear_center_interp) {
- switch (param) {
- case SI_PARAM_LINEAR_CENTROID:
- case SI_PARAM_LINEAR_SAMPLE:
- return SI_PARAM_LINEAR_CENTER;
- }
- }
-
- return param;
-}
-
/**
* Interpolate a fragment shader input.
*
}
}
-/* LLVMGetParam with bc_optimize resolved. */
-static LLVMValueRef get_interp_param(struct si_shader_context *ctx,
- int interp_param_idx)
-{
- LLVMBuilderRef builder = ctx->gallivm.builder;
- LLVMValueRef main_fn = ctx->main_fn;
- LLVMValueRef param = NULL;
-
- /* Handle PRIM_MASK[31] (bc_optimize). */
- if (ctx->no_prolog &&
- ((ctx->shader->key.ps.prolog.bc_optimize_for_persp &&
- interp_param_idx == SI_PARAM_PERSP_CENTROID) ||
- (ctx->shader->key.ps.prolog.bc_optimize_for_linear &&
- interp_param_idx == SI_PARAM_LINEAR_CENTROID))) {
- /* The shader should do: if (PRIM_MASK[31]) CENTROID = CENTER;
- * The hw doesn't compute CENTROID if the whole wave only
- * contains fully-covered quads.
- */
- LLVMValueRef bc_optimize =
- LLVMGetParam(main_fn, SI_PARAM_PRIM_MASK);
- bc_optimize = LLVMBuildLShr(builder,
- bc_optimize,
- LLVMConstInt(ctx->i32, 31, 0), "");
- bc_optimize = LLVMBuildTrunc(builder, bc_optimize, ctx->i1, "");
-
- if (ctx->shader->key.ps.prolog.bc_optimize_for_persp &&
- interp_param_idx == SI_PARAM_PERSP_CENTROID) {
- param = LLVMBuildSelect(builder, bc_optimize,
- LLVMGetParam(main_fn,
- SI_PARAM_PERSP_CENTER),
- LLVMGetParam(main_fn,
- SI_PARAM_PERSP_CENTROID),
- "");
- }
- if (ctx->shader->key.ps.prolog.bc_optimize_for_linear &&
- interp_param_idx == SI_PARAM_LINEAR_CENTROID) {
- param = LLVMBuildSelect(builder, bc_optimize,
- LLVMGetParam(main_fn,
- SI_PARAM_LINEAR_CENTER),
- LLVMGetParam(main_fn,
- SI_PARAM_LINEAR_CENTROID),
- "");
- }
- }
-
- if (!param)
- param = LLVMGetParam(main_fn, interp_param_idx);
- return param;
-}
-
static void declare_input_fs(
struct si_shader_context *radeon_bld,
unsigned input_index,
if (interp_param_idx == -1)
return;
else if (interp_param_idx) {
- interp_param_idx = select_interp_param(ctx,
- interp_param_idx);
- interp_param = get_interp_param(ctx, interp_param_idx);
+ interp_param = LLVMGetParam(ctx->main_fn, interp_param_idx);
}
if (decl->Semantic.Name == TGSI_SEMANTIC_COLOR &&
}
}
+/**
+ * Forward all outputs from the vertex shader to the TES. This is only used
+ * for the fixed function TCS.
+ */
static void si_copy_tcs_inputs(struct lp_build_tgsi_context *bld_base)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMValueRef rel_patch_id, invocation_id, tf_lds_offset;
+ si_copy_tcs_inputs(bld_base);
+
rel_patch_id = get_rel_patch_id(ctx);
invocation_id = unpack_param(ctx, SI_PARAM_REL_IDS, 8, 5);
tf_lds_offset = get_tcs_out_current_patch_data_offset(ctx);
return;
}
- si_copy_tcs_inputs(bld_base);
si_write_tess_factors(bld_base, rel_patch_id, invocation_id, tf_lds_offset);
}
if (interp_param_idx == -1)
return;
else if (interp_param_idx)
- interp_param = get_interp_param(ctx, interp_param_idx);
+ interp_param = LLVMGetParam(ctx->main_fn, interp_param_idx);
else
interp_param = NULL;
ctx.separate_prolog = !is_monolithic;
if (ctx.type == PIPE_SHADER_VERTEX ||
+ ctx.type == PIPE_SHADER_TESS_CTRL ||
+ ctx.type == PIPE_SHADER_TESS_EVAL ||
ctx.type == PIPE_SHADER_FRAGMENT) {
ctx.no_prolog = false;
ctx.no_epilog = false;
si_build_wrapper_function(&ctx, parts, 1 + need_prolog + need_epilog,
need_prolog ? 1 : 0);
+ } else if (is_monolithic && ctx.type == PIPE_SHADER_TESS_CTRL) {
+ LLVMValueRef parts[2];
+ union si_shader_part_key epilog_key;
+
+ parts[0] = ctx.main_fn;
+
+ memset(&epilog_key, 0, sizeof(epilog_key));
+ epilog_key.tcs_epilog.states = shader->key.tcs.epilog;
+ si_build_tcs_epilog_function(&ctx, &epilog_key);
+ parts[1] = ctx.main_fn;
+
+ si_build_wrapper_function(&ctx, parts, 2, 0);
+ } else if (is_monolithic && ctx.type == PIPE_SHADER_TESS_EVAL &&
+ !shader->key.tes.as_es) {
+ LLVMValueRef parts[2];
+ union si_shader_part_key epilog_key;
+
+ parts[0] = ctx.main_fn;
+
+ si_get_vs_epilog_key(shader, &shader->key.tes.epilog, &epilog_key);
+ si_build_vs_epilog_function(&ctx, &epilog_key);
+ parts[1] = ctx.main_fn;
+
+ si_build_wrapper_function(&ctx, parts, 2, 0);
} else if (is_monolithic && ctx.type == PIPE_SHADER_FRAGMENT) {
LLVMValueRef parts[3];
union si_shader_part_key prolog_key;
&shader->key.tes.epilog);
}
+/**
+ * Compile the TCS epilog function. This writes tesselation factors to memory
+ * based on the output primitive type of the tesselator (determined by TES).
+ */
+static void si_build_tcs_epilog_function(struct si_shader_context *ctx,
+ union si_shader_part_key *key)
+{
+ struct gallivm_state *gallivm = &ctx->gallivm;
+ struct lp_build_tgsi_context *bld_base = &ctx->soa.bld_base;
+ LLVMTypeRef params[16];
+ LLVMValueRef func;
+ int last_sgpr, num_params;
+
+ /* Declare inputs. Only RW_BUFFERS and TESS_FACTOR_OFFSET are used. */
+ params[SI_PARAM_RW_BUFFERS] = const_array(ctx->v16i8, SI_NUM_RW_BUFFERS);
+ params[SI_PARAM_CONST_BUFFERS] = ctx->i64;
+ params[SI_PARAM_SAMPLERS] = ctx->i64;
+ params[SI_PARAM_IMAGES] = ctx->i64;
+ params[SI_PARAM_SHADER_BUFFERS] = ctx->i64;
+ params[SI_PARAM_TCS_OFFCHIP_LAYOUT] = ctx->i32;
+ params[SI_PARAM_TCS_OUT_OFFSETS] = ctx->i32;
+ params[SI_PARAM_TCS_OUT_LAYOUT] = ctx->i32;
+ params[SI_PARAM_TCS_IN_LAYOUT] = ctx->i32;
+ params[ctx->param_oc_lds = SI_PARAM_TCS_OC_LDS] = ctx->i32;
+ params[SI_PARAM_TESS_FACTOR_OFFSET] = ctx->i32;
+ last_sgpr = SI_PARAM_TESS_FACTOR_OFFSET;
+ num_params = last_sgpr + 1;
+
+ params[num_params++] = ctx->i32; /* patch index within the wave (REL_PATCH_ID) */
+ params[num_params++] = ctx->i32; /* invocation ID within the patch */
+ params[num_params++] = ctx->i32; /* LDS offset where tess factors should be loaded from */
+
+ /* Create the function. */
+ si_create_function(ctx, "tcs_epilog", NULL, 0, params, num_params, last_sgpr);
+ declare_tess_lds(ctx);
+ func = ctx->main_fn;
+
+ si_write_tess_factors(bld_base,
+ LLVMGetParam(func, last_sgpr + 1),
+ LLVMGetParam(func, last_sgpr + 2),
+ LLVMGetParam(func, last_sgpr + 3));
+
+ LLVMBuildRetVoid(gallivm->builder);
+}
+
/**
* Compile the TCS epilog. This writes tesselation factors to memory based on
* the output primitive type of the tesselator (determined by TES).
struct si_shader shader = {};
struct si_shader_context ctx;
struct gallivm_state *gallivm = &ctx.gallivm;
- struct lp_build_tgsi_context *bld_base = &ctx.soa.bld_base;
- LLVMTypeRef params[16];
- LLVMValueRef func;
- int last_sgpr, num_params;
bool status = true;
si_init_shader_ctx(&ctx, sscreen, &shader, tm);
ctx.type = PIPE_SHADER_TESS_CTRL;
shader.key.tcs.epilog = key->tcs_epilog.states;
- /* Declare inputs. Only RW_BUFFERS and TESS_FACTOR_OFFSET are used. */
- params[SI_PARAM_RW_BUFFERS] = const_array(ctx.v16i8, SI_NUM_RW_BUFFERS);
- params[SI_PARAM_CONST_BUFFERS] = ctx.i64;
- params[SI_PARAM_SAMPLERS] = ctx.i64;
- params[SI_PARAM_IMAGES] = ctx.i64;
- params[SI_PARAM_SHADER_BUFFERS] = ctx.i64;
- params[SI_PARAM_TCS_OFFCHIP_LAYOUT] = ctx.i32;
- params[SI_PARAM_TCS_OUT_OFFSETS] = ctx.i32;
- params[SI_PARAM_TCS_OUT_LAYOUT] = ctx.i32;
- params[SI_PARAM_TCS_IN_LAYOUT] = ctx.i32;
- params[ctx.param_oc_lds = SI_PARAM_TCS_OC_LDS] = ctx.i32;
- params[SI_PARAM_TESS_FACTOR_OFFSET] = ctx.i32;
- last_sgpr = SI_PARAM_TESS_FACTOR_OFFSET;
- num_params = last_sgpr + 1;
-
- params[num_params++] = ctx.i32; /* patch index within the wave (REL_PATCH_ID) */
- params[num_params++] = ctx.i32; /* invocation ID within the patch */
- params[num_params++] = ctx.i32; /* LDS offset where tess factors should be loaded from */
-
- /* Create the function. */
- si_create_function(&ctx, "tcs_epilog", NULL, 0, params, num_params, last_sgpr);
- declare_tess_lds(&ctx);
- func = ctx.main_fn;
-
- si_write_tess_factors(bld_base,
- LLVMGetParam(func, last_sgpr + 1),
- LLVMGetParam(func, last_sgpr + 2),
- LLVMGetParam(func, last_sgpr + 3));
+ si_build_tcs_epilog_function(&ctx, key);
/* Compile. */
- LLVMBuildRetVoid(gallivm->builder);
si_llvm_finalize_module(&ctx,
r600_extra_shader_checks(&sscreen->b, PIPE_SHADER_TESS_CTRL));