[Mesa-dev] [PATCH 2/9] gallium/tgsi: start adding hw atomics (v2)
Marek Olšák
maraeo at gmail.com
Fri Nov 3 23:10:47 UTC 2017
On Fri, Nov 3, 2017 at 8:24 AM, Dave Airlie <airlied at gmail.com> wrote:
> From: Dave Airlie <airlied at redhat.com>
>
> This adds support for a hw atomic counters to TGSI.
>
> A new register file for storing atomic counters is added,
> along with a new atomic counter semantic, along with docs
> for both.
>
> v2: drop semantic, move hw counter to backend,
> Ilia pointed out SSO would have busted my plan, and he
> was right.
>
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> ---
> src/gallium/auxiliary/tgsi/tgsi_strings.c | 1 +
> src/gallium/auxiliary/tgsi/tgsi_ureg.c | 79 ++++++++++++++++++++++++++++++
> src/gallium/auxiliary/tgsi/tgsi_ureg.h | 7 +++
> src/gallium/docs/source/tgsi.rst | 37 ++++++++++++--
> src/gallium/include/pipe/p_shader_tokens.h | 1 +
> src/gallium/include/pipe/p_state.h | 1 +
> 6 files changed, 122 insertions(+), 4 deletions(-)
>
> diff --git a/src/gallium/auxiliary/tgsi/tgsi_strings.c b/src/gallium/auxiliary/tgsi/tgsi_strings.c
> index 0872db9..4f28b49 100644
> --- a/src/gallium/auxiliary/tgsi/tgsi_strings.c
> +++ b/src/gallium/auxiliary/tgsi/tgsi_strings.c
> @@ -58,6 +58,7 @@ static const char *tgsi_file_names[] =
> "BUFFER",
> "MEMORY",
> "CONSTBUF",
> + "HWATOMIC",
> };
>
> const char *tgsi_semantic_names[TGSI_SEMANTIC_COUNT] =
> diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
> index b26434c..7e88f9b 100644
> --- a/src/gallium/auxiliary/tgsi/tgsi_ureg.c
> +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
> @@ -80,6 +80,7 @@ struct ureg_tokens {
> #define UREG_MAX_SYSTEM_VALUE PIPE_MAX_ATTRIBS
> #define UREG_MAX_OUTPUT (4 * PIPE_MAX_SHADER_OUTPUTS)
> #define UREG_MAX_CONSTANT_RANGE 32
> +#define UREG_MAX_HW_ATOMIC_RANGE 32
> #define UREG_MAX_IMMEDIATE 4096
> #define UREG_MAX_ADDR 3
> #define UREG_MAX_ARRAY_TEMPS 256
> @@ -92,6 +93,15 @@ struct const_decl {
> unsigned nr_constant_ranges;
> };
>
> +struct hw_atomic_decl {
> + struct {
> + unsigned first;
> + unsigned last;
> + unsigned array_id;
> + } hw_atomic_range[UREG_MAX_HW_ATOMIC_RANGE];
> + unsigned nr_hw_atomic_ranges;
> +};
> +
> #define DOMAIN_DECL 0
> #define DOMAIN_INSN 1
>
> @@ -182,6 +192,8 @@ struct ureg_program
>
> struct const_decl const_decls[PIPE_MAX_CONSTANT_BUFFERS];
>
> + struct hw_atomic_decl hw_atomic_decls[PIPE_MAX_HW_ATOMIC_BUFFERS];
> +
> unsigned properties[TGSI_PROPERTY_COUNT];
>
> unsigned nr_addrs;
> @@ -583,6 +595,28 @@ out:
> return ureg_src_dimension(src, 0);
> }
>
> +
> +/* Returns a new hw atomic register. Keep track of which have been
> + * referred to so that we can emit decls later.
> + */
> +void
> +ureg_DECL_hw_atomic(struct ureg_program *ureg,
> + unsigned first,
> + unsigned last,
> + unsigned buffer_id,
> + unsigned array_id)
> +{
> + struct hw_atomic_decl *decl = &ureg->hw_atomic_decls[buffer_id];
> +
> + if (decl->nr_hw_atomic_ranges < UREG_MAX_HW_ATOMIC_RANGE) {
> + uint i = decl->nr_hw_atomic_ranges++;
> +
> + decl->hw_atomic_range[i].first = first;
> + decl->hw_atomic_range[i].last = last;
> + decl->hw_atomic_range[i].array_id = array_id;
> + }
> +}
> +
> static struct ureg_dst alloc_temporary( struct ureg_program *ureg,
> boolean local )
> {
> @@ -1501,6 +1535,35 @@ emit_decl_semantic(struct ureg_program *ureg,
> }
> }
>
> +static void
> +emit_decl_atomic_2d(struct ureg_program *ureg,
> + unsigned first,
> + unsigned last,
> + unsigned index2D,
> + unsigned array_id)
> +{
> + union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, array_id ? 4 : 3);
> +
> + out[0].value = 0;
> + out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
> + out[0].decl.NrTokens = 3;
> + out[0].decl.File = TGSI_FILE_HW_ATOMIC;
> + out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
> + out[0].decl.Dimension = 1;
> + out[0].decl.Array = array_id != 0;
> +
> + out[1].value = 0;
> + out[1].decl_range.First = first;
> + out[1].decl_range.Last = last;
> +
> + out[2].value = 0;
> + out[2].decl_dim.Index2D = index2D;
> +
> + if (array_id) {
> + out[3].value = 0;
> + out[3].array.ArrayID = array_id;
> + }
> +}
>
> static void
> emit_decl_fs(struct ureg_program *ureg,
> @@ -1908,6 +1971,22 @@ static void emit_decls( struct ureg_program *ureg )
> }
> }
>
> + for (i = 0; i < PIPE_MAX_HW_ATOMIC_BUFFERS; i++) {
> + struct hw_atomic_decl *decl = &ureg->hw_atomic_decls[i];
> +
> + if (decl->nr_hw_atomic_ranges) {
> + uint j;
> +
> + for (j = 0; j < decl->nr_hw_atomic_ranges; j++) {
> + emit_decl_atomic_2d(ureg,
> + decl->hw_atomic_range[j].first,
> + decl->hw_atomic_range[j].last,
> + i,
> + decl->hw_atomic_range[j].array_id);
> + }
> + }
> + }
> +
> if (ureg->nr_temps) {
> unsigned array = 0;
> for (i = 0; i < ureg->nr_temps;) {
> diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.h b/src/gallium/auxiliary/tgsi/tgsi_ureg.h
> index e88c2c1..96aef25 100644
> --- a/src/gallium/auxiliary/tgsi/tgsi_ureg.h
> +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.h
> @@ -316,6 +316,13 @@ struct ureg_src
> ureg_DECL_constant( struct ureg_program *,
> unsigned index );
>
> +void
> +ureg_DECL_hw_atomic(struct ureg_program *ureg,
> + unsigned first,
> + unsigned last,
> + unsigned buffer_id,
> + unsigned array_id);
> +
> struct ureg_dst
> ureg_DECL_temporary( struct ureg_program * );
>
> diff --git a/src/gallium/docs/source/tgsi.rst b/src/gallium/docs/source/tgsi.rst
> index 1a51fe9..9aace1a 100644
> --- a/src/gallium/docs/source/tgsi.rst
> +++ b/src/gallium/docs/source/tgsi.rst
> @@ -2638,9 +2638,11 @@ logical operations. In this context atomicity means that another
> concurrent memory access operation that affects the same memory
> location is guaranteed to be performed strictly before or after the
> entire execution of the atomic operation. The resource may be a BUFFER,
> -IMAGE, or MEMORY. In the case of an image, the offset works the same as for
> -``LOAD`` and ``STORE``, specified above. These atomic operations may
> -only be used with 32-bit integer image formats.
> +IMAGE, ATOMIC, or MEMORY. In the case of an image, the offset works
> +the same as for ``LOAD`` and ``STORE``, specified above. For atomic
> +counters, the offset is an immediate index to the base hw atomic
> +counter for this operation.
> +These atomic operations may only be used with 32-bit integer image formats.
>
> .. opcode:: ATOMUADD - Atomic integer addition
>
> @@ -3440,7 +3442,6 @@ TGSI_SEMANTIC_SUBGROUP_LT_MASK
> A bit mask of ``bit index < TGSI_SEMANTIC_SUBGROUP_INVOCATION``, i.e.
> ``(1 << subgroup_invocation) - 1`` in arbitrary precision arithmetic.
>
> -
> Declaration Interpolate
> ^^^^^^^^^^^^^^^^^^^^^^^
>
> @@ -3517,6 +3518,34 @@ accessing a misaligned address is undefined.
> Usage of the STORE opcode is only allowed if the WR (writable) flag
> is set.
>
> +Hardware Atomic Register File
> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +Hardware atomics are declared as a 2D array with an optional array id.
> +
> +The first member of the dimension is the buffer resource the atomic
> +is located in.
> +The second member is a range into the buffer resource, either for
> +one or multiple counters. If this is an array, the declaration will have
> +an unique array id.
> +
> +Each counter is 4 bytes in size, and index and ranges are in counters not bytes.
> +DCL BUFFER[0], ATOMIC
> +DCL ATOMIC[0][0]
> +DCL ATOMIC[0][1]
> +
> +This declares two atomics, one at the start of the buffer and one in the
> +second 4 bytes.
> +
> +DCL BUFFER[0], ATOMIC
> +DCL BUFFER[1], ATOMIC
Why are there BUFFER declarations?
Marek
> +DCL ATOMIC[0][0]
> +DCL ATOMIC[1][0]
> +DCL ATOMIC[1][1..3], ARRAY(1)
> +
> +This declares 5 atomics, one in buffer 0 at 0,
> +one in buffer 1 at 0, and an array of 3 atomics in
> +the buffer 1, starting at 1.
>
> Properties
> ^^^^^^^^^^^^^^^^^^^^^^^^
> diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h
> index 97deef7..4e95789 100644
> --- a/src/gallium/include/pipe/p_shader_tokens.h
> +++ b/src/gallium/include/pipe/p_shader_tokens.h
> @@ -75,6 +75,7 @@ enum tgsi_file_type {
> TGSI_FILE_BUFFER,
> TGSI_FILE_MEMORY,
> TGSI_FILE_CONSTBUF,
> + TGSI_FILE_HW_ATOMIC,
> TGSI_FILE_COUNT, /**< how many TGSI_FILE_ types */
> };
>
> diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h
> index 90dc561..10d21db 100644
> --- a/src/gallium/include/pipe/p_state.h
> +++ b/src/gallium/include/pipe/p_state.h
> @@ -75,6 +75,7 @@ extern "C" {
> #define PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT 2
> #define PIPE_MAX_WINDOW_RECTANGLES 8
>
> +#define PIPE_MAX_HW_ATOMIC_BUFFERS 32
>
> struct pipe_reference
> {
> --
> 2.9.5
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list