summaryrefslogtreecommitdiffstats
path: root/src/gallium/auxiliary/gallivm
diff options
context:
space:
mode:
authorZack Rusin <[email protected]>2013-02-18 04:00:19 -0800
committerZack Rusin <[email protected]>2013-03-27 03:53:02 -0700
commite96f4e3b853ff5fe4d927c69695c0b5f1966d448 (patch)
tree0ec9030bb93df2046f73afed5bcb999ca8af5e68 /src/gallium/auxiliary/gallivm
parentedcebe665d1204269f5961079a63c5f632cf3f07 (diff)
gallium/llvm: implement geometry shaders in the llvm paths
This commits implements code generation of the geometry shaders in the SOA paths. All the code is there but bugs are likely present. Signed-off-by: Zack Rusin <[email protected]> Reviewed-by: Brian Paul <[email protected]> Reviewed-by: José Fonseca <[email protected]>
Diffstat (limited to 'src/gallium/auxiliary/gallivm')
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_tgsi.h27
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c173
2 files changed, 187 insertions, 13 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
index 6e65e126d68..62d4707371f 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
@@ -61,6 +61,7 @@ struct tgsi_shader_info;
struct lp_build_mask_context;
struct gallivm_state;
struct lp_derivatives;
+struct lp_build_tgsi_gs_iface;
enum lp_build_tex_modifier {
@@ -224,7 +225,8 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
const LLVMValueRef (*inputs)[4],
LLVMValueRef (*outputs)[4],
struct lp_build_sampler_soa *sampler,
- const struct tgsi_shader_info *info);
+ const struct tgsi_shader_info *info,
+ const struct lp_build_tgsi_gs_iface *gs_iface);
void
@@ -361,6 +363,24 @@ struct lp_build_tgsi_context
void (*emit_epilogue)(struct lp_build_tgsi_context*);
};
+struct lp_build_tgsi_gs_iface
+{
+ LLVMValueRef input;
+ void (*emit_vertex)(struct lp_build_tgsi_context * bld_base,
+ LLVMValueRef (*outputs)[4],
+ LLVMValueRef emitted_vertices_vec,
+ void *user_data);
+ void (*end_primitive)(struct lp_build_tgsi_context * bld_base,
+ LLVMValueRef verts_per_prim_vec,
+ LLVMValueRef emitted_prims_vec,
+ void *user_data);
+ void (*gs_epilogue)(struct lp_build_tgsi_context * bld_base,
+ LLVMValueRef total_emitted_vertices_vec,
+ LLVMValueRef emitted_prims_vec,
+ void *user_data);
+ void *user_data;
+};
+
struct lp_build_tgsi_soa_context
{
struct lp_build_tgsi_context bld_base;
@@ -368,6 +388,11 @@ struct lp_build_tgsi_soa_context
/* Builder for scalar elements of shader's data type (float) */
struct lp_build_context elem_bld;
+ const struct lp_build_tgsi_gs_iface *gs_iface;
+ LLVMValueRef emitted_prims_vec;
+ LLVMValueRef total_emitted_vertices_vec;
+ LLVMValueRef emitted_vertices_vec;
+
LLVMValueRef consts_ptr;
const LLVMValueRef *pos;
const LLVMValueRef (*inputs)[TGSI_NUM_CHANNELS];
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
index cafc61f60f6..6f174a5b50e 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
@@ -437,6 +437,26 @@ lp_get_output_ptr(struct lp_build_tgsi_soa_context *bld,
}
}
+/*
+ * If we have indirect addressing in outputs copy our alloca array
+ * to the outputs slots specified by the caller to make sure
+ * our outputs are delivered consistently via the same interface.
+ */
+static void
+gather_outputs(struct lp_build_tgsi_soa_context * bld)
+{
+ if ((bld->indirect_files & (1 << TGSI_FILE_OUTPUT))) {
+ unsigned index, chan;
+ assert(bld->bld_base.info->num_outputs <=
+ bld->bld_base.info->file_max[TGSI_FILE_OUTPUT] + 1);
+ for (index = 0; index < bld->bld_base.info->num_outputs; ++index) {
+ for (chan = 0; chan < TGSI_NUM_CHANNELS; ++chan) {
+ bld->outputs[index][chan] = lp_get_output_ptr(bld, index, chan);
+ }
+ }
+ }
+}
+
/**
* Gather vector.
* XXX the lp_build_gather() function should be capable of doing this
@@ -757,6 +777,60 @@ emit_fetch_input(
return res;
}
+
+static LLVMValueRef
+emit_fetch_gs_input(
+ struct lp_build_tgsi_context * bld_base,
+ const struct tgsi_full_src_register * reg,
+ enum tgsi_opcode_type stype,
+ unsigned swizzle)
+{
+ struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
+ struct gallivm_state *gallivm = bld->bld_base.base.gallivm;
+ LLVMBuilderRef builder = gallivm->builder;
+ //struct lp_build_context *uint_bld = &bld_base->uint_bld;
+ LLVMValueRef attrib_index = NULL;
+ LLVMValueRef vertex_index = NULL;
+ LLVMValueRef swizzle_index = lp_build_const_int32(gallivm, swizzle);
+ LLVMValueRef indices[3];
+ LLVMValueRef res;
+
+ if (reg->Register.Indirect) {
+ attrib_index = get_indirect_index(bld,
+ reg->Register.File,
+ reg->Register.Index,
+ &reg->Indirect);
+ } else {
+ attrib_index = lp_build_const_int32(gallivm, reg->Register.Index);
+ }
+
+ if (reg->Dimension.Indirect) {
+ vertex_index = get_indirect_index(bld,
+ reg->Register.File,
+ reg->Dimension.Index,
+ &reg->DimIndirect);
+ } else {
+ vertex_index = lp_build_const_int32(gallivm, reg->Dimension.Index);
+ }
+
+ indices[0] = vertex_index;
+ indices[1] = attrib_index;
+ indices[2] = swizzle_index;
+
+ res = LLVMBuildGEP(builder, bld->gs_iface->input, indices, 3, "");
+ res = LLVMBuildLoad(builder, res, "");
+
+ assert(res);
+
+ if (stype == TGSI_TYPE_UNSIGNED) {
+ res = LLVMBuildBitCast(builder, res, bld_base->uint_bld.vec_type, "");
+ } else if (stype == TGSI_TYPE_SIGNED) {
+ res = LLVMBuildBitCast(builder, res, bld_base->int_bld.vec_type, "");
+ }
+
+ return res;
+}
+
static LLVMValueRef
emit_fetch_temporary(
struct lp_build_tgsi_context * bld_base,
@@ -2081,6 +2155,66 @@ sviewinfo_emit(
emit_size_query(bld, emit_data->inst, emit_data->output, TRUE);
}
+static LLVMValueRef
+mask_to_one_vec(struct lp_build_tgsi_context *bld_base)
+{
+ struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
+ LLVMBuilderRef builder = bld->bld_base.base.gallivm->builder;
+ LLVMValueRef one_vec = bld_base->int_bld.one;
+ struct lp_exec_mask *exec_mask = &bld->exec_mask;
+
+ if (exec_mask->has_mask) {
+ one_vec = LLVMBuildAnd(builder, one_vec, exec_mask->exec_mask, "");
+ }
+ one_vec = LLVMBuildAnd(builder, one_vec,
+ lp_build_mask_value(bld->mask), "");
+ return one_vec;
+}
+
+static void
+emit_vertex(
+ const struct lp_build_tgsi_action * action,
+ struct lp_build_tgsi_context * bld_base,
+ struct lp_build_emit_data * emit_data)
+{
+ struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
+ LLVMBuilderRef builder = bld->bld_base.base.gallivm->builder;
+
+ if (bld->gs_iface->emit_vertex) {
+ LLVMValueRef masked_ones = mask_to_one_vec(bld_base);
+ gather_outputs(bld);
+ bld->gs_iface->emit_vertex(&bld->bld_base, bld->outputs,
+ bld->total_emitted_vertices_vec,
+ bld->gs_iface->user_data);
+ bld->emitted_vertices_vec =
+ LLVMBuildAdd(builder, bld->emitted_vertices_vec, masked_ones, "");
+ bld->total_emitted_vertices_vec =
+ LLVMBuildAdd(builder, bld->total_emitted_vertices_vec, masked_ones, "");
+ }
+}
+
+
+static void
+end_primitive(
+ const struct lp_build_tgsi_action * action,
+ struct lp_build_tgsi_context * bld_base,
+ struct lp_build_emit_data * emit_data)
+{
+ struct lp_build_tgsi_soa_context * bld = lp_soa_context(bld_base);
+ LLVMBuilderRef builder = bld->bld_base.base.gallivm->builder;
+
+ if (bld->gs_iface->end_primitive) {
+ LLVMValueRef masked_ones = mask_to_one_vec(bld_base);
+ bld->gs_iface->end_primitive(&bld->bld_base,
+ bld->emitted_vertices_vec,
+ bld->emitted_prims_vec,
+ bld->gs_iface->user_data);
+ bld->emitted_prims_vec =
+ LLVMBuildAdd(builder, bld->emitted_prims_vec, masked_ones, "");
+ bld->emitted_vertices_vec = bld_base->uint_bld.zero;
+ }
+}
+
static void
cal_emit(
const struct lp_build_tgsi_action * action,
@@ -2324,7 +2458,7 @@ static void emit_prologue(struct lp_build_tgsi_context * bld_base)
/* If we have indirect addressing in inputs we need to copy them into
* our alloca array to be able to iterate over them */
- if (bld->indirect_files & (1 << TGSI_FILE_INPUT)) {
+ if (bld->indirect_files & (1 << TGSI_FILE_INPUT) && !bld->gs_iface) {
unsigned index, chan;
LLVMTypeRef vec_type = bld_base->base.vec_type;
LLVMValueRef array_size = lp_build_const_int32(gallivm,
@@ -2349,6 +2483,13 @@ static void emit_prologue(struct lp_build_tgsi_context * bld_base)
}
}
}
+
+ if (bld->gs_iface) {
+ struct lp_build_context *uint_bld = &bld->bld_base.uint_bld;
+ bld->emitted_prims_vec = uint_bld->zero;
+ bld->emitted_vertices_vec = uint_bld->zero;
+ bld->total_emitted_vertices_vec = uint_bld->zero;
+ }
}
static void emit_epilogue(struct lp_build_tgsi_context * bld_base)
@@ -2361,16 +2502,14 @@ static void emit_epilogue(struct lp_build_tgsi_context * bld_base)
}
/* If we have indirect addressing in outputs we need to copy our alloca array
- * to the outputs slots specified by the called */
- if (bld->indirect_files & (1 << TGSI_FILE_OUTPUT)) {
- unsigned index, chan;
- assert(bld_base->info->num_outputs <=
- bld_base->info->file_max[TGSI_FILE_OUTPUT] + 1);
- for (index = 0; index < bld_base->info->num_outputs; ++index) {
- for (chan = 0; chan < TGSI_NUM_CHANNELS; ++chan) {
- bld->outputs[index][chan] = lp_get_output_ptr(bld, index, chan);
- }
- }
+ * to the outputs slots specified by the caller */
+ if (bld->gs_iface) {
+ bld->gs_iface->gs_epilogue(&bld->bld_base,
+ bld->total_emitted_vertices_vec,
+ bld->emitted_prims_vec,
+ bld->gs_iface->user_data);
+ } else {
+ gather_outputs(bld);
}
}
@@ -2385,7 +2524,8 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
const LLVMValueRef (*inputs)[TGSI_NUM_CHANNELS],
LLVMValueRef (*outputs)[TGSI_NUM_CHANNELS],
struct lp_build_sampler_soa *sampler,
- const struct tgsi_shader_info *info)
+ const struct tgsi_shader_info *info,
+ const struct lp_build_tgsi_gs_iface *gs_iface)
{
struct lp_build_tgsi_soa_context bld;
@@ -2463,6 +2603,15 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
bld.bld_base.op_actions[TGSI_OPCODE_SAMPLE_L].emit = sample_l_emit;
bld.bld_base.op_actions[TGSI_OPCODE_SVIEWINFO].emit = sviewinfo_emit;
+ if (gs_iface) {
+ /* inputs are always indirect with gs */
+ bld.indirect_files |= (1 << TGSI_FILE_INPUT);
+ bld.gs_iface = gs_iface;
+ bld.bld_base.emit_fetch_funcs[TGSI_FILE_INPUT] = emit_fetch_gs_input;
+ bld.bld_base.op_actions[TGSI_OPCODE_EMIT].emit = emit_vertex;
+ bld.bld_base.op_actions[TGSI_OPCODE_ENDPRIM].emit = end_primitive;
+ }
+
lp_exec_mask_init(&bld.exec_mask, &bld.bld_base.base);
bld.system_values = *system_values;