diff --git a/src/broadcom/compiler/v3d_compiler.h b/src/broadcom/compiler/v3d_compiler.h index df81f0757e2..207e29733aa 100644 --- a/src/broadcom/compiler/v3d_compiler.h +++ b/src/broadcom/compiler/v3d_compiler.h @@ -336,6 +336,11 @@ struct v3d_fs_key { uint8_t swap_color_rb; /* Mask of which render targets need to be written as 32-bit floats */ uint8_t f32_color_rb; + /* Masks of which render targets need to be written as ints/uints. + * Used by gallium to work around lost information in TGSI. + */ + uint8_t int_color_rb; + uint8_t uint_color_rb; uint8_t alpha_test_func; uint8_t logicop_func; uint32_t point_sprite_mask; diff --git a/src/broadcom/compiler/vir.c b/src/broadcom/compiler/vir.c index 05f557fbcd0..ff9405e6c12 100644 --- a/src/broadcom/compiler/vir.c +++ b/src/broadcom/compiler/vir.c @@ -756,6 +756,36 @@ v3d_set_fs_prog_data_inputs(struct v3d_compile *c, } } +static void +v3d_fixup_fs_output_types(struct v3d_compile *c) +{ + nir_foreach_variable(var, &c->s->outputs) { + uint32_t mask = 0; + + switch (var->data.location) { + case FRAG_RESULT_COLOR: + mask = ~0; + break; + case FRAG_RESULT_DATA0: + case FRAG_RESULT_DATA1: + case FRAG_RESULT_DATA2: + case FRAG_RESULT_DATA3: + mask = 1 << (var->data.location - FRAG_RESULT_DATA0); + break; + } + + if (c->fs_key->int_color_rb & mask) { + var->type = + glsl_vector_type(GLSL_TYPE_INT, + glsl_get_components(var->type)); + } else if (c->fs_key->uint_color_rb & mask) { + var->type = + glsl_vector_type(GLSL_TYPE_UINT, + glsl_get_components(var->type)); + } + } +} + uint64_t *v3d_compile_fs(const struct v3d_compiler *compiler, struct v3d_fs_key *key, struct v3d_fs_prog_data *prog_data, @@ -768,6 +798,9 @@ uint64_t *v3d_compile_fs(const struct v3d_compiler *compiler, c->fs_key = key; + if (key->int_color_rb || key->uint_color_rb) + v3d_fixup_fs_output_types(c); + v3d_lower_nir(c); if (key->light_twoside) diff --git a/src/gallium/drivers/vc5/vc5_context.h b/src/gallium/drivers/vc5/vc5_context.h index 28b2e165a9d..1ab5a6b1532 100644 --- a/src/gallium/drivers/vc5/vc5_context.h +++ b/src/gallium/drivers/vc5/vc5_context.h @@ -132,6 +132,13 @@ struct vc5_uncompiled_shader { struct v3d_varying_slot *tf_outputs; uint16_t tf_specs[PIPE_MAX_SO_BUFFERS]; uint32_t num_tf_specs; + + /** + * Flag for if the NIR in this shader originally came from TGSI. If + * so, we need to do some fixups at compile time, due to missing + * information in TGSI that exists in NIR. + */ + bool was_tgsi; }; struct vc5_compiled_shader { diff --git a/src/gallium/drivers/vc5/vc5_program.c b/src/gallium/drivers/vc5/vc5_program.c index ae3850a64b3..87c21abe8b1 100644 --- a/src/gallium/drivers/vc5/vc5_program.c +++ b/src/gallium/drivers/vc5/vc5_program.c @@ -170,6 +170,8 @@ vc5_shader_state_create(struct pipe_context *pctx, fprintf(stderr, "\n"); } s = tgsi_to_nir(cso->tokens, &v3d_nir_options); + + so->was_tgsi = true; } NIR_PASS_V(s, nir_opt_global_to_local); @@ -414,6 +416,13 @@ vc5_update_compiled_fs(struct vc5_context *vc5, uint8_t prim_mode) desc->channel[0].size == 32) { key->f32_color_rb |= 1 << i; } + + if (vc5->prog.bind_fs->was_tgsi) { + if (util_format_is_pure_uint(cbuf->format)) + key->uint_color_rb |= 1 << i; + else if (util_format_is_pure_sint(cbuf->format)) + key->int_color_rb |= 1 << i; + } } if (key->is_points) {