aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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. */