From 04e672257c770412dd04011929662ee969e24106 Mon Sep 17 00:00:00 2001 From: Gert Wollny Date: Tue, 15 Jan 2019 10:32:17 +0100 Subject: [PATCH] virgl: Enable passing arrays as input to fragment shaders This is needed to properly handle interpolateAt* when the input to be interpolated is passed as array in the original GLSL. Currently, the the GLSL compiler would lower selecting the correct input so that the interpolant parameter to interpolateAt* is a temporary, and this can not be used to create a valid shader on the host side, because here the parameter must a shader input. By allowing the passing the created TGSI allows to create proper GLSL. This is related to the virglrenderer bug https://gitlab.freedesktop.org/virgl/virglrenderer/issues/74 v2: Squash the two patches handling these flags into another Signed-off-by: Gert Wollny Reviewed-by: Gurchetan Singh --- src/gallium/drivers/virgl/virgl_hw.h | 2 + src/gallium/drivers/virgl/virgl_screen.c | 5 ++ src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 64 +++++++++++++++++++--- 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/src/gallium/drivers/virgl/virgl_hw.h b/src/gallium/drivers/virgl/virgl_hw.h index 8a56e1d53a8..949a1f545e7 100644 --- a/src/gallium/drivers/virgl/virgl_hw.h +++ b/src/gallium/drivers/virgl/virgl_hw.h @@ -241,6 +241,8 @@ enum virgl_formats { #define VIRGL_CAP_MULTI_DRAW_INDIRECT (1 << 21) #define VIRGL_CAP_INDIRECT_PARAMS (1 << 22) #define VIRGL_CAP_TRANSFORM_FEEDBACK3 (1 << 23) +#define VIRGL_CAP_INDIRECT_INPUT_ADDR (1 << 25) + /* virgl bind flags - these are compatible with mesa 10.5 gallium. * but are fixed, no other should be passed to virgl either. diff --git a/src/gallium/drivers/virgl/virgl_screen.c b/src/gallium/drivers/virgl/virgl_screen.c index 2e2af36f587..66fadddc262 100644 --- a/src/gallium/drivers/virgl/virgl_screen.c +++ b/src/gallium/drivers/virgl/virgl_screen.c @@ -357,6 +357,8 @@ virgl_get_param(struct pipe_screen *screen, enum pipe_cap param) return vscreen->vws->supports_fences; case PIPE_CAP_DEST_SURFACE_SRGB_CONTROL: return vscreen->caps.caps.v2.capability_bits & VIRGL_CAP_SRGB_WRITE_CONTROL; + case PIPE_CAP_TGSI_SKIP_SHRINK_IO_ARRAYS: + return vscreen->caps.caps.v2.capability_bits & VIRGL_CAP_INDIRECT_INPUT_ADDR; default: return u_pipe_screen_get_param_defaults(screen, param); } @@ -395,6 +397,9 @@ virgl_get_shader_param(struct pipe_screen *screen, case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: return 1; + case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE: + case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR: + return vscreen->caps.caps.v2.capability_bits & VIRGL_CAP_INDIRECT_INPUT_ADDR; case PIPE_SHADER_CAP_MAX_INPUTS: if (vscreen->caps.caps.v1.glsl_level < 150) return vscreen->caps.caps.v2.max_vertex_attribs; diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index f8771125f45..37e78406c5c 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -2715,6 +2715,42 @@ shrink_array_declarations(struct inout_decl *decls, unsigned count, } } + +static void +mark_array_io(struct inout_decl *decls, unsigned count, + GLbitfield64* usage_mask, + GLbitfield64 double_usage_mask, + GLbitfield* patch_usage_mask) +{ + unsigned i; + int j; + + /* Fix array declarations by removing unused array elements at both ends + * of the arrays. For example, mat4[3] where only mat[1] is used. + */ + for (i = 0; i < count; i++) { + struct inout_decl *decl = &decls[i]; + if (!decl->array_id) + continue; + + /* When not all entries of an array are accessed, we mark them as used + * here anyway, to ensure that the input/output mapping logic doesn't get + * confused. + * + * TODO This happens when an array isn't used via indirect access, which + * some game ports do (at least eON-based). There is an optimization + * opportunity here by replacing the array declaration with non-array + * declarations of those slots that are actually used. + */ + for (j = 0; j < (int)decl->size; ++j) { + if (decl->mesa_index >= VARYING_SLOT_PATCH0) + *patch_usage_mask |= BITFIELD64_BIT(decl->mesa_index - VARYING_SLOT_PATCH0 + j); + else + *usage_mask |= BITFIELD64_BIT(decl->mesa_index + j); + } + } +} + void glsl_to_tgsi_visitor::visit(ir_dereference_array *ir) { @@ -7157,14 +7193,28 @@ get_mesa_program_tgsi(struct gl_context *ctx, } do_set_program_inouts(shader->ir, prog, shader->Stage); + _mesa_copy_linked_program_data(shader_program, shader); - shrink_array_declarations(v->inputs, v->num_inputs, - &prog->info.inputs_read, - prog->DualSlotInputs, - &prog->info.patch_inputs_read); - shrink_array_declarations(v->outputs, v->num_outputs, - &prog->info.outputs_written, 0ULL, - &prog->info.patch_outputs_written); + + if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_SKIP_SHRINK_IO_ARRAYS)) { + mark_array_io(v->inputs, v->num_inputs, + &prog->info.inputs_read, + prog->DualSlotInputs, + &prog->info.patch_inputs_read); + + mark_array_io(v->outputs, v->num_outputs, + &prog->info.outputs_written, 0ULL, + &prog->info.patch_outputs_written); + } else { + shrink_array_declarations(v->inputs, v->num_inputs, + &prog->info.inputs_read, + prog->DualSlotInputs, + &prog->info.patch_inputs_read); + shrink_array_declarations(v->outputs, v->num_outputs, + &prog->info.outputs_written, 0ULL, + &prog->info.patch_outputs_written); + } + count_resources(v, prog); /* The GLSL IR won't be needed anymore. */ -- 2.30.2