static void
attribs_update_simple(struct lp_build_interp_soa_context *bld,
struct gallivm_state *gallivm,
- int quad_start_index,
LLVMValueRef loop_iter,
int start,
int end)
unsigned attrib;
LLVMValueRef pixoffx;
LLVMValueRef pixoffy;
+ LLVMValueRef ptr;
/* could do this with code-generated passed in pixel offsets too */
- if (bld->dynamic_offsets) {
- LLVMValueRef ptr;
- assert(loop_iter);
- ptr = LLVMBuildGEP(builder, bld->xoffset_store, &loop_iter, 1, "");
- pixoffx = LLVMBuildLoad(builder, ptr, "");
- ptr = LLVMBuildGEP(builder, bld->yoffset_store, &loop_iter, 1, "");
- pixoffy = LLVMBuildLoad(builder, ptr, "");
- }
- else {
- calc_offsets(coeff_bld, quad_start_index, &pixoffx, &pixoffy);
- }
+ assert(loop_iter);
+ ptr = LLVMBuildGEP(builder, bld->xoffset_store, &loop_iter, 1, "");
+ pixoffx = LLVMBuildLoad(builder, ptr, "");
+ ptr = LLVMBuildGEP(builder, bld->yoffset_store, &loop_iter, 1, "");
+ pixoffy = LLVMBuildLoad(builder, ptr, "");
pixoffx = LLVMBuildFAdd(builder, pixoffx,
lp_build_broadcast_scalar(coeff_bld, bld->x), "");
attrib_name(a, attrib, chan, ".a");
attrib_name(dadq, attrib, chan, ".dadq");
- if (bld->dynamic_offsets) {
- bld->a[attrib][chan] = lp_build_alloca(gallivm,
- LLVMTypeOf(a), "");
- LLVMBuildStore(builder, a, bld->a[attrib][chan]);
- }
- else {
- bld->a[attrib][chan] = a;
- }
+ bld->a[attrib][chan] = lp_build_alloca(gallivm,
+ LLVMTypeOf(a), "");
+ LLVMBuildStore(builder, a, bld->a[attrib][chan]);
bld->dadq[attrib][chan] = dadq;
}
}
static void
attribs_update(struct lp_build_interp_soa_context *bld,
struct gallivm_state *gallivm,
- int quad_start_index,
LLVMValueRef loop_iter,
int start,
int end)
{
LLVMBuilderRef builder = gallivm->builder;
struct lp_build_context *coeff_bld = &bld->coeff_bld;
- LLVMValueRef shuffle = lp_build_const_int_vec(gallivm, coeff_bld->type, quad_start_index);
LLVMValueRef oow = NULL;
unsigned attrib;
unsigned chan;
- assert(quad_start_index < 4);
-
for(attrib = start; attrib < end; ++attrib) {
const unsigned mask = bld->mask[attrib];
const unsigned interp = bld->interp[attrib];
LLVMValueRef a;
if (interp == LP_INTERP_CONSTANT ||
interp == LP_INTERP_FACING) {
- a = bld->a[attrib][chan];
- if (bld->dynamic_offsets) {
- a = LLVMBuildLoad(builder, a, "");
- }
+ a = LLVMBuildLoad(builder, bld->a[attrib][chan], "");
}
else if (interp == LP_INTERP_POSITION) {
assert(attrib > 0);
* Broadcast the attribute value for this quad into all elements
*/
- if (bld->dynamic_offsets) {
+ {
/* stored as vector load as float */
LLVMTypeRef ptr_type = LLVMPointerType(LLVMFloatTypeInContext(
gallivm->context), 0);
a = LLVMBuildLoad(builder, ptr, "");
a = lp_build_broadcast_scalar(&bld->coeff_bld, a);
}
- else {
- a = LLVMBuildShuffleVector(builder,
- a, coeff_bld->undef, shuffle, "");
- }
/*
* Get the derivatives.
const struct lp_shader_input *inputs,
LLVMBuilderRef builder,
struct lp_type type,
- boolean dynamic_offsets,
LLVMValueRef a0_ptr,
LLVMValueRef dadx_ptr,
LLVMValueRef dady_ptr,
if (coeff_type.length > 4) {
bld->simple_interp = TRUE;
- if (dynamic_offsets) {
- /* XXX this should use a global static table */
+ {
+ /* XXX this should use a global static table */
unsigned i;
unsigned num_loops = 16 / type.length;
LLVMValueRef pixoffx, pixoffy, index;
LLVMValueRef ptr;
- bld->dynamic_offsets = TRUE;
bld->xoffset_store = lp_build_array_alloca(gallivm,
lp_build_vec_type(gallivm, type),
lp_build_const_int32(gallivm, num_loops),
}
else {
bld->simple_interp = FALSE;
- if (dynamic_offsets) {
- bld->dynamic_offsets = TRUE;
- }
coeffs_init(bld, a0_ptr, dadx_ptr, dady_ptr);
}
}
-/**
+/*
* Advance the position and inputs to the given quad within the block.
*/
-void
-lp_build_interp_soa_update_inputs(struct lp_build_interp_soa_context *bld,
- struct gallivm_state *gallivm,
- int quad_start_index)
-{
- assert(quad_start_index < 4);
-
- if (bld->simple_interp) {
- attribs_update_simple(bld, gallivm, quad_start_index, NULL, 1, bld->num_attribs);
- }
- else {
- attribs_update(bld, gallivm, quad_start_index, NULL, 1, bld->num_attribs);
- }
-}
-
-void
-lp_build_interp_soa_update_pos(struct lp_build_interp_soa_context *bld,
- struct gallivm_state *gallivm,
- int quad_start_index)
-{
- assert(quad_start_index < 4);
-
- if (bld->simple_interp) {
- attribs_update_simple(bld, gallivm, quad_start_index, NULL, 0, 1);
- }
- else {
- attribs_update(bld, gallivm, quad_start_index, NULL, 0, 1);
- }
-}
void
lp_build_interp_soa_update_inputs_dyn(struct lp_build_interp_soa_context *bld,
LLVMValueRef quad_start_index)
{
if (bld->simple_interp) {
- attribs_update_simple(bld, gallivm, 0, quad_start_index, 1, bld->num_attribs);
+ attribs_update_simple(bld, gallivm, quad_start_index, 1, bld->num_attribs);
}
else {
- attribs_update(bld, gallivm, 0, quad_start_index, 1, bld->num_attribs);
+ attribs_update(bld, gallivm, quad_start_index, 1, bld->num_attribs);
}
}
LLVMValueRef quad_start_index)
{
if (bld->simple_interp) {
- attribs_update_simple(bld, gallivm, 0, quad_start_index, 0, 1);
+ attribs_update_simple(bld, gallivm, quad_start_index, 0, 1);
}
else {
- attribs_update(bld, gallivm, 0, quad_start_index, 0, 1);
+ attribs_update(bld, gallivm, quad_start_index, 0, 1);
}
}
}
-/**
- * Generate the fragment shader, depth/stencil test, and alpha tests.
- * \param i which quad in the tile, in range [0,3]
- * \param partial_mask if 1, do mask_input testing
- */
-static void
-generate_fs(struct gallivm_state *gallivm,
- struct lp_fragment_shader *shader,
- const struct lp_fragment_shader_variant_key *key,
- LLVMBuilderRef builder,
- struct lp_type type,
- LLVMValueRef context_ptr,
- unsigned i,
- struct lp_build_interp_soa_context *interp,
- struct lp_build_sampler_soa *sampler,
- LLVMValueRef *pmask,
- LLVMValueRef (*color)[4],
- LLVMValueRef depth_ptr,
- LLVMValueRef facing,
- unsigned partial_mask,
- LLVMValueRef mask_input,
- LLVMValueRef thread_data_ptr)
-{
- const struct util_format_description *zs_format_desc = NULL;
- const struct tgsi_token *tokens = shader->base.tokens;
- LLVMTypeRef vec_type;
- LLVMValueRef consts_ptr;
- LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][TGSI_NUM_CHANNELS];
- LLVMValueRef z;
- LLVMValueRef zs_value = NULL;
- LLVMValueRef stencil_refs[2];
- struct lp_build_mask_context mask;
- boolean simple_shader = (shader->info.base.file_count[TGSI_FILE_SAMPLER] == 0 &&
- shader->info.base.num_inputs < 3 &&
- shader->info.base.num_instructions < 8);
- const boolean dual_source_blend = key->blend.rt[0].blend_enable &&
- util_blend_state_is_dual(&key->blend, 0);
- unsigned attrib;
- unsigned chan;
- unsigned cbuf;
- unsigned depth_mode;
- struct lp_bld_tgsi_system_values system_values;
-
- memset(&system_values, 0, sizeof(system_values));
-
- if (key->depth.enabled ||
- key->stencil[0].enabled ||
- key->stencil[1].enabled) {
-
- zs_format_desc = util_format_description(key->zsbuf_format);
- assert(zs_format_desc);
-
- if (!shader->info.base.writes_z) {
- if (key->alpha.enabled || shader->info.base.uses_kill)
- /* With alpha test and kill, can do the depth test early
- * and hopefully eliminate some quads. But need to do a
- * special deferred depth write once the final mask value
- * is known.
- */
- depth_mode = EARLY_DEPTH_TEST | LATE_DEPTH_WRITE;
- else
- depth_mode = EARLY_DEPTH_TEST | EARLY_DEPTH_WRITE;
- }
- else {
- depth_mode = LATE_DEPTH_TEST | LATE_DEPTH_WRITE;
- }
-
- if (!(key->depth.enabled && key->depth.writemask) &&
- !(key->stencil[0].enabled && key->stencil[0].writemask))
- depth_mode &= ~(LATE_DEPTH_WRITE | EARLY_DEPTH_WRITE);
- }
- else {
- depth_mode = 0;
- }
-
- assert(i < 4);
-
- stencil_refs[0] = lp_jit_context_stencil_ref_front_value(gallivm, context_ptr);
- stencil_refs[1] = lp_jit_context_stencil_ref_back_value(gallivm, context_ptr);
-
- vec_type = lp_build_vec_type(gallivm, type);
-
- consts_ptr = lp_jit_context_constants(gallivm, context_ptr);
-
- memset(outputs, 0, sizeof outputs);
-
- /* Declare the color and z variables */
- for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) {
- for(chan = 0; chan < TGSI_NUM_CHANNELS; ++chan) {
- color[cbuf][chan] = lp_build_alloca(gallivm, vec_type, "color");
- }
- }
- if (dual_source_blend) {
- assert(key->nr_cbufs <= 1);
- for(chan = 0; chan < TGSI_NUM_CHANNELS; ++chan) {
- color[1][chan] = lp_build_alloca(gallivm, vec_type, "color1");
- }
- }
-
- /* do triangle edge testing */
- if (partial_mask) {
- *pmask = generate_quad_mask(gallivm, type,
- i*type.length/4, mask_input);
- }
- else {
- *pmask = lp_build_const_int_vec(gallivm, type, ~0);
- }
-
- /* 'mask' will control execution based on quad's pixel alive/killed state */
- lp_build_mask_begin(&mask, gallivm, type, *pmask);
-
- if (!(depth_mode & EARLY_DEPTH_TEST) && !simple_shader)
- lp_build_mask_check(&mask);
-
- lp_build_interp_soa_update_pos(interp, gallivm, i*type.length/4);
- z = interp->pos[2];
-
- if (depth_mode & EARLY_DEPTH_TEST) {
- lp_build_depth_stencil_test(gallivm,
- &key->depth,
- key->stencil,
- type,
- zs_format_desc,
- &mask,
- stencil_refs,
- z,
- depth_ptr, facing,
- &zs_value,
- !simple_shader);
-
- if (depth_mode & EARLY_DEPTH_WRITE) {
- lp_build_depth_write(gallivm, type, zs_format_desc, depth_ptr, zs_value);
- }
- }
-
- lp_build_interp_soa_update_inputs(interp, gallivm, i*type.length/4);
-
- /* Build the actual shader */
- lp_build_tgsi_soa(gallivm, tokens, type, &mask,
- consts_ptr, &system_values,
- interp->inputs,
- outputs, sampler, &shader->info.base, NULL);
-
- /* Alpha test */
- if (key->alpha.enabled) {
- int color0 = find_output_by_semantic(&shader->info.base,
- TGSI_SEMANTIC_COLOR,
- 0);
-
- if (color0 != -1 && outputs[color0][3]) {
- const struct util_format_description *cbuf_format_desc;
- LLVMValueRef alpha = LLVMBuildLoad(builder, outputs[color0][3], "alpha");
- LLVMValueRef alpha_ref_value;
-
- alpha_ref_value = lp_jit_context_alpha_ref_value(gallivm, context_ptr);
- alpha_ref_value = lp_build_broadcast(gallivm, vec_type, alpha_ref_value);
-
- cbuf_format_desc = util_format_description(key->cbuf_format[0]);
-
- lp_build_alpha_test(gallivm, key->alpha.func, type, cbuf_format_desc,
- &mask, alpha, alpha_ref_value,
- (depth_mode & LATE_DEPTH_TEST) != 0);
- }
- }
-
- /* Late Z test */
- if (depth_mode & LATE_DEPTH_TEST) {
- int pos0 = find_output_by_semantic(&shader->info.base,
- TGSI_SEMANTIC_POSITION,
- 0);
-
- if (pos0 != -1 && outputs[pos0][2]) {
- z = LLVMBuildLoad(builder, outputs[pos0][2], "output.z");
- }
-
- lp_build_depth_stencil_test(gallivm,
- &key->depth,
- key->stencil,
- type,
- zs_format_desc,
- &mask,
- stencil_refs,
- z,
- depth_ptr, facing,
- &zs_value,
- !simple_shader);
- /* Late Z write */
- if (depth_mode & LATE_DEPTH_WRITE) {
- lp_build_depth_write(gallivm, type, zs_format_desc, depth_ptr, zs_value);
- }
- }
- else if ((depth_mode & EARLY_DEPTH_TEST) &&
- (depth_mode & LATE_DEPTH_WRITE))
- {
- /* Need to apply a reduced mask to the depth write. Reload the
- * depth value, update from zs_value with the new mask value and
- * write that out.
- */
- lp_build_deferred_depth_write(gallivm,
- type,
- zs_format_desc,
- &mask,
- depth_ptr,
- zs_value);
- }
-
-
- /* Color write */
- for (attrib = 0; attrib < shader->info.base.num_outputs; ++attrib)
- {
- unsigned cbuf = shader->info.base.output_semantic_index[attrib];
- if ((shader->info.base.output_semantic_name[attrib] == TGSI_SEMANTIC_COLOR) &&
- ((cbuf < key->nr_cbufs) || (cbuf == 1 && dual_source_blend)))
- {
- unsigned cbuf = shader->info.base.output_semantic_index[attrib];
- for(chan = 0; chan < TGSI_NUM_CHANNELS; ++chan) {
- if(outputs[attrib][chan]) {
- /* XXX: just initialize outputs to point at colors[] and
- * skip this.
- */
- LLVMValueRef out = LLVMBuildLoad(builder, outputs[attrib][chan], "");
- lp_build_name(out, "color%u.%u.%c", i, attrib, "rgba"[chan]);
- LLVMBuildStore(builder, out, color[cbuf][chan]);
- }
- }
- }
- }
-
- if (key->occlusion_count) {
- LLVMValueRef counter = lp_jit_thread_data_counter(gallivm, thread_data_ptr);
- lp_build_name(counter, "counter");
- lp_build_occlusion_count(gallivm, type,
- lp_build_mask_value(&mask), counter);
- }
-
- *pmask = lp_build_mask_end(&mask);
-}
-
-
/**
* Generate the fragment shader, depth/stencil test, and alpha tests.
*/
unsigned chan;
unsigned cbuf;
boolean cbuf0_write_all;
- boolean try_loop = TRUE;
const boolean dual_source_blend = key->blend.rt[0].blend_enable &&
util_blend_state_is_dual(&key->blend, 0);
zs_format_desc = util_format_description(key->zsbuf_format);
- if (!try_loop) {
- /*
- * The shader input interpolation info is not explicitely baked in the
- * shader key, but everything it derives from (TGSI, and flatshade) is
- * already included in the shader key.
- */
- lp_build_interp_soa_init(&interp,
- gallivm,
- shader->info.base.num_inputs,
- inputs,
- builder, fs_type,
- FALSE,
- a0_ptr, dadx_ptr, dady_ptr,
- x, y);
-
- /* loop over quads in the block */
- for(i = 0; i < num_fs; ++i) {
- LLVMValueRef depth_offset = LLVMConstInt(int32_type,
- i*fs_type.length*zs_format_desc->block.bits/8,
- 0);
- LLVMValueRef out_color[PIPE_MAX_COLOR_BUFS][TGSI_NUM_CHANNELS];
- LLVMValueRef depth_ptr_i;
-
- depth_ptr_i = LLVMBuildGEP(builder, depth_ptr, &depth_offset, 1, "");
-
- generate_fs(gallivm,
- shader, key,
- builder,
- fs_type,
- context_ptr,
- i,
- &interp,
- sampler,
- &fs_mask[i], /* output */
- out_color,
- depth_ptr_i,
- facing,
- partial_mask,
- mask_input,
- thread_data_ptr);
-
- for (cbuf = 0; cbuf < key->nr_cbufs; cbuf++) {
- for (chan = 0; chan < TGSI_NUM_CHANNELS; ++chan)
- fs_out_color[cbuf][chan][i] =
- out_color[cbuf * !cbuf0_write_all][chan];
- }
- if (dual_source_blend) {
- /* only support one dual source blend target hence always use output 1 */
- for (chan = 0; chan < TGSI_NUM_CHANNELS; ++chan)
- fs_out_color[1][chan][i] =
- out_color[1][chan];
- }
- }
- }
- else {
+ {
unsigned depth_bits = zs_format_desc->block.bits/8;
LLVMValueRef num_loop = lp_build_const_int32(gallivm, num_fs);
LLVMTypeRef mask_type = lp_build_int_vec_type(gallivm, fs_type);
shader->info.base.num_inputs,
inputs,
builder, fs_type,
- TRUE,
a0_ptr, dadx_ptr, dady_ptr,
x, y);