[Mesa-dev] [PATCH HACK] radeonsi: patch shader binary to use LEGACY variants of MUL/MAD
Ilia Mirkin
imirkin at alum.mit.edu
Tue Jan 24 03:56:52 UTC 2017
On Mon, Jan 23, 2017 at 10:51 PM, Ilia Mirkin <imirkin at alum.mit.edu> wrote:
> There are variants of the instructions that don't have legacy versions
> that we don't prevent from being selected. As such, I think this
> approach is doomed.
>
> Not for inclusion upstream.
> ---
>
> On top of everything, totally untested. And also unsure I got the instruction
> patching logic right - just going off of a brief glance at the GCN docs.
>
> src/gallium/drivers/radeonsi/si_pipe.c | 2 +-
> src/gallium/drivers/radeonsi/si_shader.c | 53 +++++++++++++++++++++++++++++++-
> 2 files changed, 53 insertions(+), 2 deletions(-)
>
> diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c
> index b41e5da..a49ebca 100644
> --- a/src/gallium/drivers/radeonsi/si_pipe.c
> +++ b/src/gallium/drivers/radeonsi/si_pipe.c
> @@ -414,6 +414,7 @@ static int si_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
> case PIPE_CAP_TGSI_ARRAY_COMPONENTS:
> case PIPE_CAP_TGSI_CAN_READ_OUTPUTS:
> case PIPE_CAP_GLSL_OPTIMIZE_CONSERVATIVELY:
> + case PIPE_CAP_TGSI_MUL_ZERO_WINS:
> return 1;
>
> case PIPE_CAP_RESOURCE_FROM_USER_MEMORY:
> @@ -465,7 +466,6 @@ static int si_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
> case PIPE_CAP_MAX_WINDOW_RECTANGLES:
> case PIPE_CAP_NATIVE_FENCE_FD:
> case PIPE_CAP_TGSI_FS_FBFETCH:
> - case PIPE_CAP_TGSI_MUL_ZERO_WINS:
> return 0;
>
> case PIPE_CAP_QUERY_BUFFER_OBJECT:
> diff --git a/src/gallium/drivers/radeonsi/si_shader.c b/src/gallium/drivers/radeonsi/si_shader.c
> index 5ca974e..fece98f 100644
> --- a/src/gallium/drivers/radeonsi/si_shader.c
> +++ b/src/gallium/drivers/radeonsi/si_shader.c
> @@ -6132,6 +6132,57 @@ static unsigned si_get_shader_binary_size(struct si_shader *shader)
> return size;
> }
>
> +static void si_shader_binary_upload_patch(struct si_shader *shader, unsigned *ptr)
> +{
> + const struct radeon_shader_binary *mainb = &shader->binary;
> +
> + if (!shader->selector->info.properties[TGSI_PROPERTY_MUL_ZERO_WINS]) {
> + util_memcpy_cpu_to_le32(ptr, mainb->code, mainb->code_size);
> + return;
> + }
> +
> + /* Binary-patch V_MUL_F32 (GCN1: 0x8, GCN3: 0x5) into V_MUL_LEGACY_F32
> + * (GCN1: 0x7, 0x4) and V_MAD_F32 (GCN1: 0x141, GCN3: 0x1c1) into
> + * V_MAD_LEGACY_F32 (GCN1: 0x140, GCN3: 0x1c0).
> + *
> + * TODO: Also replace V_MAC_F32? The legacy variant is gone on GCN3.
> + *
> + * Detect the VOP2 and VOP3a encodings and patch them. All other
> + * encodings are 8 bytes, just pass them through.
> + */
> + const unsigned mul_op =
> + shader->selector->screen->b.chip_class < VI ? 0x8 : 0x5;
> + const unsigned mad_op =
> + shader->selector->screen->b.chip_class < VI ? 0x141 : 0x1c1;
> + int i;
> + unsigned *code = (unsigned *)mainb->code;
> + for (i = 0; i < mainb->code_size / 4; i++) {
> + if ((*code & (1U << 31)) == 0) {
> + unsigned opcode = (*code >> 25) & 0x7f;
> + if (opcode == mul_op)
> + *ptr++ = util_cpu_to_le32(
> + (*code++ & 0x80ffffff) |
That should probably be 0x81ffffff, on the off chance someone actually
tries this.
> + (opcode - 1) << 25);
> + else
> + *ptr++ = util_cpu_to_le32(*code++);
> + } else if ((*code & (0xFCU << 24)) == 0xD0000000) {
> + unsigned opcode = (*code >> 16) & 0x3ff;
> + if (opcode == mad_op || opcode == 0x100 + mul_op)
> + *ptr++ = util_cpu_to_le32(
> + (*code++ & 0xfc00ffff) |
> + (opcode - 1) << 16);
> + else
> + *ptr++ = util_cpu_to_le32(*code++);
> + *ptr++ = util_cpu_to_le32(*code++);
> + i++;
> + } else {
> + *ptr++ = util_cpu_to_le32(*code++);
> + *ptr++ = util_cpu_to_le32(*code++);
> + i++;
> + }
> + }
> +}
> +
> int si_shader_binary_upload(struct si_screen *sscreen, struct si_shader *shader)
> {
> const struct radeon_shader_binary *prolog =
> @@ -6163,7 +6214,7 @@ int si_shader_binary_upload(struct si_screen *sscreen, struct si_shader *shader)
> ptr += prolog->code_size;
> }
>
> - util_memcpy_cpu_to_le32(ptr, mainb->code, mainb->code_size);
> + si_shader_binary_upload_patch(shader, (unsigned *)ptr);
> ptr += mainb->code_size;
>
> if (epilog)
> --
> 2.10.2
>
More information about the mesa-dev
mailing list