aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGert Wollny <[email protected]>2019-01-15 10:32:17 +0100
committerGert Wollny <[email protected]>2019-04-10 11:09:40 +0200
commit04e672257c770412dd04011929662ee969e24106 (patch)
treef5cbba8a9dd50df82c594584adb8787af939e243
parent872519c663ca813b87c8e2cd1c2ee90eb086e17c (diff)
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 <[email protected]> Reviewed-by: Gurchetan Singh <[email protected]>
-rw-r--r--src/gallium/drivers/virgl/virgl_hw.h2
-rw-r--r--src/gallium/drivers/virgl/virgl_screen.c5
-rw-r--r--src/mesa/state_tracker/st_glsl_to_tgsi.cpp64
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. */