summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/radeonsi/si_shader.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/radeonsi/si_shader.c')
-rw-r--r--src/gallium/drivers/radeonsi/si_shader.c203
1 files changed, 136 insertions, 67 deletions
diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
index c1d3edc7143..34b84eb81d9 100644
--- a/src/gallium/drivers/radeonsi/si_shader.c
+++ b/src/gallium/drivers/radeonsi/si_shader.c
@@ -86,8 +86,9 @@ struct si_shader_context
LLVMValueRef const_buffers[SI_NUM_CONST_BUFFERS];
LLVMValueRef lds;
LLVMValueRef *constants[SI_NUM_CONST_BUFFERS];
- LLVMValueRef sampler_views[SI_NUM_SAMPLER_VIEWS];
- LLVMValueRef sampler_states[SI_NUM_SAMPLER_STATES];
+ LLVMValueRef sampler_views[SI_NUM_SAMPLERS];
+ LLVMValueRef sampler_states[SI_NUM_SAMPLERS];
+ LLVMValueRef fmasks[SI_NUM_USER_SAMPLERS];
LLVMValueRef so_buffers[4];
LLVMValueRef esgs_ring;
LLVMValueRef gsvs_ring[4];
@@ -2286,7 +2287,6 @@ static void si_export_mrt_color(struct lp_build_tgsi_context *bld_base,
{
struct si_shader_context *si_shader_ctx = si_shader_context(bld_base);
struct lp_build_context *base = &bld_base->base;
- LLVMValueRef args[9];
int i;
/* Clamp color */
@@ -2308,27 +2308,46 @@ static void si_export_mrt_color(struct lp_build_tgsi_context *bld_base,
color[3] = si_scale_alpha_by_sample_mask(bld_base, color[3]);
/* If last_cbuf > 0, FS_COLOR0_WRITES_ALL_CBUFS is true. */
- if (index == 0 &&
- si_shader_ctx->shader->key.ps.last_cbuf > 0) {
- for (int c = 1; c <= si_shader_ctx->shader->key.ps.last_cbuf; c++) {
+ if (si_shader_ctx->shader->key.ps.last_cbuf > 0) {
+ LLVMValueRef args[8][9];
+ int c, last = -1;
+
+ /* Get the export arguments, also find out what the last one is. */
+ for (c = 0; c <= si_shader_ctx->shader->key.ps.last_cbuf; c++) {
si_llvm_init_export_args(bld_base, color,
- V_008DFC_SQ_EXP_MRT + c, args);
+ V_008DFC_SQ_EXP_MRT + c, args[c]);
+ if (args[c][0] != bld_base->uint_bld.zero)
+ last = c;
+ }
+
+ /* Emit all exports. */
+ for (c = 0; c <= si_shader_ctx->shader->key.ps.last_cbuf; c++) {
+ if (is_last && last == c) {
+ args[c][1] = bld_base->uint_bld.one; /* whether the EXEC mask is valid */
+ args[c][2] = bld_base->uint_bld.one; /* DONE bit */
+ } else if (args[c][0] == bld_base->uint_bld.zero)
+ continue; /* unnecessary NULL export */
+
lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export",
LLVMVoidTypeInContext(base->gallivm->context),
- args, 9, 0);
+ args[c], 9, 0);
}
+ } else {
+ LLVMValueRef args[9];
+
+ /* Export */
+ si_llvm_init_export_args(bld_base, color, V_008DFC_SQ_EXP_MRT + index,
+ args);
+ if (is_last) {
+ args[1] = bld_base->uint_bld.one; /* whether the EXEC mask is valid */
+ args[2] = bld_base->uint_bld.one; /* DONE bit */
+ } else if (args[0] == bld_base->uint_bld.zero)
+ return; /* unnecessary NULL export */
+
+ lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export",
+ LLVMVoidTypeInContext(base->gallivm->context),
+ args, 9, 0);
}
-
- /* Export */
- si_llvm_init_export_args(bld_base, color, V_008DFC_SQ_EXP_MRT + index,
- args);
- if (is_last) {
- args[1] = bld_base->uint_bld.one; /* whether the EXEC mask is valid */
- args[2] = bld_base->uint_bld.one; /* DONE bit */
- }
- lp_build_intrinsic(base->gallivm->builder, "llvm.SI.export",
- LLVMVoidTypeInContext(base->gallivm->context),
- args, 9, 0);
}
static void si_export_null(struct lp_build_tgsi_context *bld_base)
@@ -2363,19 +2382,43 @@ static void si_llvm_emit_fs_epilogue(struct lp_build_tgsi_context * bld_base)
int last_color_export = -1;
int i;
- /* If there are no outputs, add a dummy export. */
- if (!info->num_outputs) {
- si_export_null(bld_base);
- return;
- }
-
/* Determine the last export. If MRTZ is present, it's always last.
* Otherwise, find the last color export.
*/
- if (!info->writes_z && !info->writes_stencil && !info->writes_samplemask)
- for (i = 0; i < info->num_outputs; i++)
- if (info->output_semantic_name[i] == TGSI_SEMANTIC_COLOR)
+ if (!info->writes_z && !info->writes_stencil && !info->writes_samplemask) {
+ unsigned spi_format = shader->key.ps.spi_shader_col_format;
+
+ /* Don't export NULL and return if alpha-test is enabled. */
+ if (shader->key.ps.alpha_func != PIPE_FUNC_ALWAYS &&
+ shader->key.ps.alpha_func != PIPE_FUNC_NEVER &&
+ (spi_format & 0xf) == 0)
+ spi_format |= V_028714_SPI_SHADER_32_AR;
+
+ for (i = 0; i < info->num_outputs; i++) {
+ unsigned index = info->output_semantic_index[i];
+
+ if (info->output_semantic_name[i] != TGSI_SEMANTIC_COLOR)
+ continue;
+
+ /* If last_cbuf > 0, FS_COLOR0_WRITES_ALL_CBUFS is true. */
+ if (shader->key.ps.last_cbuf > 0) {
+ /* Just set this if any of the colorbuffers are enabled. */
+ if (spi_format &
+ ((1llu << (4 * (shader->key.ps.last_cbuf + 1))) - 1))
+ last_color_export = i;
+ continue;
+ }
+
+ if ((spi_format >> (index * 4)) & 0xf)
last_color_export = i;
+ }
+
+ /* If there are no outputs, export NULL. */
+ if (last_color_export == -1) {
+ si_export_null(bld_base);
+ return;
+ }
+ }
for (i = 0; i < info->num_outputs; i++) {
unsigned semantic_name = info->output_semantic_name[i];
@@ -2480,13 +2523,58 @@ static void set_tex_fetch_args(struct gallivm_state *gallivm,
static const struct lp_build_tgsi_action tex_action;
+enum desc_type {
+ DESC_IMAGE,
+ DESC_FMASK,
+ DESC_SAMPLER
+};
+
+static LLVMTypeRef const_array(LLVMTypeRef elem_type, int num_elements)
+{
+ return LLVMPointerType(LLVMArrayType(elem_type, num_elements),
+ CONST_ADDR_SPACE);
+}
+
+/**
+ * Load an image view, fmask view. or sampler state descriptor.
+ */
+static LLVMValueRef get_sampler_desc(struct si_shader_context *si_shader_ctx,
+ LLVMValueRef index, enum desc_type type)
+{
+ struct gallivm_state *gallivm = &si_shader_ctx->radeon_bld.gallivm;
+ LLVMTypeRef i32 = LLVMInt32TypeInContext(gallivm->context);
+ LLVMBuilderRef builder = gallivm->builder;
+ LLVMValueRef ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn,
+ SI_PARAM_SAMPLERS);
+
+ switch (type) {
+ case DESC_IMAGE:
+ /* The image is at [0:7]. */
+ index = LLVMBuildMul(builder, index, LLVMConstInt(i32, 2, 0), "");
+ break;
+ case DESC_FMASK:
+ /* The FMASK is at [8:15]. */
+ index = LLVMBuildMul(builder, index, LLVMConstInt(i32, 2, 0), "");
+ index = LLVMBuildAdd(builder, index, LLVMConstInt(i32, 1, 0), "");
+ break;
+ case DESC_SAMPLER:
+ /* The sampler state is at [12:15]. */
+ index = LLVMBuildMul(builder, index, LLVMConstInt(i32, 4, 0), "");
+ index = LLVMBuildAdd(builder, index, LLVMConstInt(i32, 3, 0), "");
+ ptr = LLVMBuildPointerCast(builder, ptr,
+ const_array(LLVMVectorType(i32, 4), 0), "");
+ break;
+ }
+
+ return build_indexed_load_const(si_shader_ctx, ptr, index);
+}
+
static void tex_fetch_ptrs(
struct lp_build_tgsi_context * bld_base,
struct lp_build_emit_data * emit_data,
LLVMValueRef *res_ptr, LLVMValueRef *samp_ptr, LLVMValueRef *fmask_ptr)
{
struct si_shader_context *si_shader_ctx = si_shader_context(bld_base);
- struct gallivm_state *gallivm = bld_base->base.gallivm;
const struct tgsi_full_instruction * inst = emit_data->inst;
unsigned target = inst->Texture.Texture;
unsigned sampler_src;
@@ -2501,24 +2589,20 @@ static void tex_fetch_ptrs(
ind_index = get_indirect_index(si_shader_ctx, &reg->Indirect, reg->Register.Index);
- *res_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_SAMPLER_VIEWS);
- *res_ptr = build_indexed_load_const(si_shader_ctx, *res_ptr, ind_index);
-
- *samp_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_SAMPLER_STATES);
- *samp_ptr = build_indexed_load_const(si_shader_ctx, *samp_ptr, ind_index);
+ *res_ptr = get_sampler_desc(si_shader_ctx, ind_index, DESC_IMAGE);
if (target == TGSI_TEXTURE_2D_MSAA ||
target == TGSI_TEXTURE_2D_ARRAY_MSAA) {
- ind_index = LLVMBuildAdd(gallivm->builder, ind_index,
- lp_build_const_int32(gallivm,
- SI_FMASK_TEX_OFFSET), "");
- *fmask_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_SAMPLER_VIEWS);
- *fmask_ptr = build_indexed_load_const(si_shader_ctx, *fmask_ptr, ind_index);
+ *samp_ptr = NULL;
+ *fmask_ptr = get_sampler_desc(si_shader_ctx, ind_index, DESC_FMASK);
+ } else {
+ *samp_ptr = get_sampler_desc(si_shader_ctx, ind_index, DESC_SAMPLER);
+ *fmask_ptr = NULL;
}
} else {
*res_ptr = si_shader_ctx->sampler_views[sampler_index];
*samp_ptr = si_shader_ctx->sampler_states[sampler_index];
- *fmask_ptr = si_shader_ctx->sampler_views[SI_FMASK_TEX_OFFSET + sampler_index];
+ *fmask_ptr = si_shader_ctx->fmasks[sampler_index];
}
}
@@ -3498,12 +3582,6 @@ static void create_meta_data(struct si_shader_context *si_shader_ctx)
si_shader_ctx->const_md = LLVMMDNodeInContext(gallivm->context, args, 3);
}
-static LLVMTypeRef const_array(LLVMTypeRef elem_type, int num_elements)
-{
- return LLVMPointerType(LLVMArrayType(elem_type, num_elements),
- CONST_ADDR_SPACE);
-}
-
static void declare_streamout_params(struct si_shader_context *si_shader_ctx,
struct pipe_stream_output_info *so,
LLVMTypeRef *params, LLVMTypeRef i32,
@@ -3530,7 +3608,7 @@ static void create_function(struct si_shader_context *si_shader_ctx)
struct lp_build_tgsi_context *bld_base = &si_shader_ctx->radeon_bld.soa.bld_base;
struct gallivm_state *gallivm = bld_base->base.gallivm;
struct si_shader *shader = si_shader_ctx->shader;
- LLVMTypeRef params[SI_NUM_PARAMS], f32, i8, i32, v2i32, v3i32, v16i8, v4i32, v8i32;
+ LLVMTypeRef params[SI_NUM_PARAMS], f32, i8, i32, v2i32, v3i32, v16i8, v8i32;
unsigned i, last_array_pointer, last_sgpr, num_params;
i8 = LLVMInt8TypeInContext(gallivm->context);
@@ -3538,15 +3616,14 @@ static void create_function(struct si_shader_context *si_shader_ctx)
f32 = LLVMFloatTypeInContext(gallivm->context);
v2i32 = LLVMVectorType(i32, 2);
v3i32 = LLVMVectorType(i32, 3);
- v4i32 = LLVMVectorType(i32, 4);
v8i32 = LLVMVectorType(i32, 8);
v16i8 = LLVMVectorType(i8, 16);
params[SI_PARAM_RW_BUFFERS] = const_array(v16i8, SI_NUM_RW_BUFFERS);
params[SI_PARAM_CONST_BUFFERS] = const_array(v16i8, SI_NUM_CONST_BUFFERS);
- params[SI_PARAM_SAMPLER_STATES] = const_array(v4i32, SI_NUM_SAMPLER_STATES);
- params[SI_PARAM_SAMPLER_VIEWS] = const_array(v8i32, SI_NUM_SAMPLER_VIEWS);
- last_array_pointer = SI_PARAM_SAMPLER_VIEWS;
+ params[SI_PARAM_SAMPLERS] = const_array(v8i32, SI_NUM_SAMPLERS);
+ params[SI_PARAM_UNUSED] = LLVMPointerType(i32, CONST_ADDR_SPACE);
+ last_array_pointer = SI_PARAM_UNUSED;
switch (si_shader_ctx->type) {
case TGSI_PROCESSOR_VERTEX:
@@ -3747,34 +3824,26 @@ static void preload_samplers(struct si_shader_context *si_shader_ctx)
struct lp_build_tgsi_context * bld_base = &si_shader_ctx->radeon_bld.soa.bld_base;
struct gallivm_state * gallivm = bld_base->base.gallivm;
const struct tgsi_shader_info * info = bld_base->info;
-
unsigned i, num_samplers = info->file_max[TGSI_FILE_SAMPLER] + 1;
-
- LLVMValueRef res_ptr, samp_ptr;
LLVMValueRef offset;
if (num_samplers == 0)
return;
- res_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_SAMPLER_VIEWS);
- samp_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_SAMPLER_STATES);
-
/* Load the resources and samplers, we rely on the code sinking to do the rest */
for (i = 0; i < num_samplers; ++i) {
/* Resource */
offset = lp_build_const_int32(gallivm, i);
- si_shader_ctx->sampler_views[i] = build_indexed_load_const(si_shader_ctx, res_ptr, offset);
-
- /* Sampler */
- offset = lp_build_const_int32(gallivm, i);
- si_shader_ctx->sampler_states[i] = build_indexed_load_const(si_shader_ctx, samp_ptr, offset);
+ si_shader_ctx->sampler_views[i] =
+ get_sampler_desc(si_shader_ctx, offset, DESC_IMAGE);
/* FMASK resource */
- if (info->is_msaa_sampler[i]) {
- offset = lp_build_const_int32(gallivm, SI_FMASK_TEX_OFFSET + i);
- si_shader_ctx->sampler_views[SI_FMASK_TEX_OFFSET + i] =
- build_indexed_load_const(si_shader_ctx, res_ptr, offset);
- }
+ if (info->is_msaa_sampler[i])
+ si_shader_ctx->fmasks[i] =
+ get_sampler_desc(si_shader_ctx, offset, DESC_FMASK);
+ else
+ si_shader_ctx->sampler_states[i] =
+ get_sampler_desc(si_shader_ctx, offset, DESC_SAMPLER);
}
}