[Mesa-dev] [PATCH 1/2] gallium/include/pipe: Added interface for atomic counter buffers in pipe
Aditya Avinash
adityaavinash1 at gmail.com
Mon Jan 5 16:08:03 PST 2015
Hi,
About this patch:
1. It is not tested. I'll test it after 12th.
2. It implements atomic buffers as a surface which can be reused for
ARB_shader_image_load_store
3. You can ignore the first patch.
My questions:
1. What does R_028AC0_ALU_ATOM_CACHE_GS_0 represent?
2. What determines the values 160, 336 and 0 in
r600_emit_vs,gs,ps_atomic,constant_buffers();?
3. What does these macros represent? What are they used for?
#define R600_UCP_CONST_BUFFER R600_MAX_USER_CONST_BUFFERS
#define R600_TXQ_CONST_BUFFER R600_MAX_USER_CONST_BUFFERS + 1
#define R600_BUFFER_INFO_CONST_BUFFER R600_MAX_USER_CONST_BUFFERS + 2
#define R600_GS_RING_CONST_BUFFER R600_MAX_USER_CONST_BUFFERS + 3
#define R600_MAX_CONST_BUFFER_SIZE (4096 * sizeof(float[4])) // It
is self-explanatory here.
4. What is the function of R600_CONTEXT_INV_ATOM_CACHE?
5. Does my implementation make sense?
Thank you!!
On Sun, Jan 4, 2015 at 3:44 PM, adityaatluri <adityaavinash1 at gmail.com>
wrote:
> ---
> src/gallium/include/pipe/p_context.h | 5 +++++
> src/gallium/include/pipe/p_defines.h | 7 ++++++-
> src/gallium/include/pipe/p_state.h | 10 ++++++++++
> 3 files changed, 21 insertions(+), 1 deletion(-)
>
> diff --git a/src/gallium/include/pipe/p_context.h
> b/src/gallium/include/pipe/p_context.h
> index af5674f..bf3be31 100644
> --- a/src/gallium/include/pipe/p_context.h
> +++ b/src/gallium/include/pipe/p_context.h
> @@ -44,6 +44,7 @@ struct pipe_blit_info;
> struct pipe_box;
> struct pipe_clip_state;
> struct pipe_constant_buffer;
> +struct pipe_counter_buffer;
> struct pipe_depth_stencil_alpha_state;
> struct pipe_draw_info;
> struct pipe_fence_handle;
> @@ -201,6 +202,10 @@ struct pipe_context {
> uint shader, uint index,
> struct pipe_constant_buffer *buf );
>
> + void (*set_counter_buffer)( struct pipe_context *,
> + uint shader, uint index,
> + struct pipe_counter_buffer *buf );
> +
> void (*set_framebuffer_state)( struct pipe_context *,
> const struct pipe_framebuffer_state * );
>
> diff --git a/src/gallium/include/pipe/p_defines.h
> b/src/gallium/include/pipe/p_defines.h
> index 8c4e415..717ab6a 100644
> --- a/src/gallium/include/pipe/p_defines.h
> +++ b/src/gallium/include/pipe/p_defines.h
> @@ -341,6 +341,7 @@ enum pipe_flush_flags {
> #define PIPE_BIND_VERTEX_BUFFER (1 << 4) /* set_vertex_buffers */
> #define PIPE_BIND_INDEX_BUFFER (1 << 5) /* draw_elements */
> #define PIPE_BIND_CONSTANT_BUFFER (1 << 6) /* set_constant_buffer */
> +#define PIPE_BIND_COUNTER_BUFFER (1 << 7) /* set_counter_buffer */
> #define PIPE_BIND_DISPLAY_TARGET (1 << 8) /* flush_front_buffer */
> #define PIPE_BIND_TRANSFER_WRITE (1 << 9) /* transfer_map */
> #define PIPE_BIND_TRANSFER_READ (1 << 10) /* transfer_map */
> @@ -572,6 +573,8 @@ enum pipe_cap {
> PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE = 109,
> PIPE_CAP_SAMPLER_VIEW_TARGET = 110,
> PIPE_CAP_CLIP_HALFZ = 111,
> + PIPE_CAP_USER_COUNTER_BUFFERS = 112,
> + PIPE_CAP_COUNTER_BUFFER_OFFSET_ALIGNMENT = 113,
> };
>
> #define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 (1 << 0)
> @@ -631,7 +634,9 @@ enum pipe_shader_cap
> PIPE_SHADER_CAP_PREFERRED_IR,
> PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED,
> PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS,
> - PIPE_SHADER_CAP_DOUBLES
> + PIPE_SHADER_CAP_DOUBLES,
> + PIPE_SHADER_CAP_MAX_COUNTER_BUFFER_SIZE,
> + PIPE_SHADER_CAP_MAX_COUNTER_BUFFERS
> };
>
> /**
> diff --git a/src/gallium/include/pipe/p_state.h
> b/src/gallium/include/pipe/p_state.h
> index 43bc48b..49fae5d 100644
> --- a/src/gallium/include/pipe/p_state.h
> +++ b/src/gallium/include/pipe/p_state.h
> @@ -57,6 +57,7 @@ extern "C" {
> #define PIPE_MAX_CLIP_PLANES 8
> #define PIPE_MAX_COLOR_BUFS 8
> #define PIPE_MAX_CONSTANT_BUFFERS 32
> +#define PIPE_MAX_COUNTER_BUFFERS 32
> #define PIPE_MAX_SAMPLERS 16
> #define PIPE_MAX_SHADER_INPUTS 32
> #define PIPE_MAX_SHADER_OUTPUTS 48 /* 32 GENERICs + POS, PSIZE, FOG,
> etc. */
> @@ -462,6 +463,15 @@ struct pipe_constant_buffer {
> const void *user_buffer; /**< pointer to a user buffer if buffer ==
> NULL */
> };
>
> +/**
> + * A Counter buffer. A new buffer is set everytime a variable with
> + * atomic_uint is defined.
> + */
> +struct pipe_counter_buffer{
> + struct pipe_resource *buffer; /**< The actual buffer */
> + unsigned buffer_offset; /**< The offset to start of data in buffer in
> bytes */
> + const void *user_buffer; /**< The buffer which is created by the
> compiler */
> +};
>
> /**
> * A stream output target. The structure specifies the range vertices can
> --
> 1.9.1
>
>
> From c80ca0e4704b8fc325e109d1770f6c4900d14cec Mon Sep 17 00:00:00 2001
> From: adityaatluri <adityaavinash1 at gmail.com>
> Date: Sun, 4 Jan 2015 16:37:43 -0500
> Subject: [PATCH 2/2] drivers/r600: added atomic buffer bindings from mesa
> to
> R600 backend as a surface
>
> ---
> src/gallium/drivers/r600/r600_hw_context.c | 3 ++
> src/gallium/drivers/r600/r600_pipe.h | 9 ++++
> src/gallium/drivers/r600/r600_state.c | 66
> +++++++++++++++++++++++++
> src/gallium/drivers/r600/r600_state_common.c | 69
> +++++++++++++++++++++++++++
> src/gallium/drivers/r600/r600d.h | 11 +++++
> src/gallium/drivers/radeon/r600_pipe_common.c | 2 +-
> 6 files changed, 159 insertions(+), 1 deletion(-)
>
> diff --git a/src/gallium/drivers/r600/r600_hw_context.c
> b/src/gallium/drivers/r600/r600_hw_context.c
> index b6fa3b0..53bc1ab 100644
> --- a/src/gallium/drivers/r600/r600_hw_context.c
> +++ b/src/gallium/drivers/r600/r600_hw_context.c
> @@ -338,14 +338,17 @@ void r600_begin_new_cs(struct r600_context *ctx)
> for (shader = 0; shader < PIPE_SHADER_TYPES; shader++) {
> struct r600_constbuf_state *constbuf =
> &ctx->constbuf_state[shader];
> struct r600_textures_info *samplers =
> &ctx->samplers[shader];
> + struct r600_atombuf_state *atombuf =
> &ctx->atomic_buffer[shader];
>
> constbuf->dirty_mask = constbuf->enabled_mask;
> samplers->views.dirty_mask = samplers->views.enabled_mask;
> samplers->states.dirty_mask =
> samplers->states.enabled_mask;
> + atombuf->dirty_mask = atombuf->enabled_mask;
>
> r600_constant_buffers_dirty(ctx, constbuf);
> r600_sampler_views_dirty(ctx, &samplers->views);
> r600_sampler_states_dirty(ctx, &samplers->states);
> + r600_atomic_buffers_dirty(ctx, atombuf);
> }
>
> r600_postflush_resume_features(&ctx->b);
> diff --git a/src/gallium/drivers/r600/r600_pipe.h
> b/src/gallium/drivers/r600/r600_pipe.h
> index 40b0328..bcdcfac 100644
> --- a/src/gallium/drivers/r600/r600_pipe.h
> +++ b/src/gallium/drivers/r600/r600_pipe.h
> @@ -347,6 +347,14 @@ struct r600_constbuf_state
> uint32_t dirty_mask;
> };
>
> +struct r600_atombuf_state
> +{
> + struct r600_atom atom;
> + struct pipe_surface ab[PIPE_MAX_ATOMIC_BUFFERS];
> + uint32_t enabled_mask;
> + uint32_t dirty_mask;
> +};
> +
> struct r600_vertexbuf_state
> {
> struct r600_atom atom;
> @@ -445,6 +453,7 @@ struct r600_context {
> struct r600_shader_stages_state shader_stages;
> struct r600_gs_rings_state gs_rings;
> struct r600_constbuf_state constbuf_state[PIPE_SHADER_TYPES];
> + struct r600_atombuf_state atomic_buffer[PIPE_SHADER_TYPES];
> struct r600_textures_info samplers[PIPE_SHADER_TYPES];
> /** Vertex buffers for fetch shaders */
> struct r600_vertexbuf_state vertex_buffer_state;
> diff --git a/src/gallium/drivers/r600/r600_state.c
> b/src/gallium/drivers/r600/r600_state.c
> index 61f5c5a..bcea22f 100644
> --- a/src/gallium/drivers/r600/r600_state.c
> +++ b/src/gallium/drivers/r600/r600_state.c
> @@ -1782,6 +1782,72 @@ static void r600_emit_ps_constant_buffers(struct
> r600_context *rctx, struct r600
> R_028940_ALU_CONST_CACHE_PS_0);
> }
>
> +static void r600_emit_atomic_buffers()
> +{
> + struct radeon_winsys_cs *cs = rctx->b.rings.gfx.cs;
> + uint32_t dirty_mask = state->dirty_mask;
> +
> + while(dirty_mask){
> + struct pipe_surface *surf;
> + struct r600_resource *rbuffer;
> + unsigned offset;
> + unsigned buffer_index = ffs(dirty_mask) - 1;
> + unsigned gs_ring_buffer = (buffer_index ==
> R600_GS_RING_ATOM_BUFFER);
> + surf = &state->ab[buffer_index];
> + rbuffer = (struct r600_resource*)surf->texture;
> + assert(rbuffer);
> +
> + offset = surf->u.buf.first_element;
> +
> + if (!gs_ring_buffer) {
> + r600_write_context_reg(cs, reg_alu_atombuf_size +
> buffer_index,// * 4,
> +
> ALIGN_BIVUP(surf->height*surf->width*sizeof(unsigned) >> 4, 16));
> + r600_write_context_reg(cs, reg_alu_atom_cache +
> buffer_index, offset >> 8);
> + }
> +
> + radeon_emit(cs, PKT3(PKT3_NOP, 0, 0));
> + radeon_emit(cs, r600_context_bo_reg(&rctx->b,
> &rctx->b.rings.gfx, rbuffer,
> + RADEON_USAGE_READ,
> RADEON_PRIO_SHADER_BUFFER_RO));
> + radeon_emit(cs, PKT3(PKT3_SET_RESOURCE, 7, 0));
> + radeon_emit(cs, (buffer_id_base + buffer_index) * 7);
> + radeon_emit(cs, offset);
> + radeon_emit(cs, rbuffer->buf->size - offset - 1);
> + radeon_emit(cs,
> + S_038008_ENDIAN_SWAP(gs_ring_buffer ?
> ENDIAN_NONE : r600_endian_swap(32)) | S_038008_STRIDE(gs_ring_buffer ? 4 :
> 16));
> + radeon_emit(cs, 0);
> + radeon_emit(cs, 0);
> + radeon_emit(cs, 0);
> + radeon_emit(cs, 0x0000000);
> +
> + radeon_emit(cs, PKT3(PKT3_NOP, 0, 0));
> + radeon_emit(cs, r600_context_bo_reloc(&rctx->b,
> +
> &rctx->b.rings.gfx,
> +
> rbuffer,
> +
> RADEON_USAGE_READ,
> +
> RADEON_PRIO_SHADER_BUFFER_RO));
> + dirty_mask &= ~(1 << buffer_index);
> + }
> + state->dirty_mask = 0;
> +}
> +
> +static void r600_emit_vs_atomic_buffers(struct r600_context *rctx, struct
> r600_atom *atom)
> +{
> + r600_emit_atomic_buffers(rctx,
> &rctx->atomic_state[PIPE_SHADER_VERTEX], 160,
> + R_028240_ALU_ATOM_BUFFER_SIZE_VS_0,
> R_028A80_ALU_ATOM_CACHE_VS_0);
> +}
> +
> +static void r600_emit_gs_atomic_buffers(struct r600_context *rctx, struct
> r600_atom *atom)
> +{
> + r600_emit_atomic_buffers(rctx,
> &rctx->atomic_state[PIPE_SHADER_GEOMETRY], 336,
> + R_028280_ALU_ATOM_BUFFER_SIZE_GS_0,
> R_028AC0_ALU_ATOM_CACHE_GS_0);
> +}
> +
> +static void r600_emit_ps_atomic_buffers(struct r600_context *rctx, struct
> r600_atom *atom)
> +{
> + r600_emit_atomic_buffers(rctx,
> &rctx->atomic_state[PIPE_SHADER_FRAGMENT], 0,
> + R_028200_ALU_ATOM_BUFFER_SIZE_PS_0,
> R_028A40_ALU_ATOM_CACHE_PS_0);
> +}
> +
> static void r600_emit_sampler_views(struct r600_context *rctx,
> struct r600_samplerview_state *state,
> unsigned resource_id_base)
> diff --git a/src/gallium/drivers/r600/r600_state_common.c
> b/src/gallium/drivers/r600/r600_state_common.c
> index c3f21cb..6d8d728 100644
> --- a/src/gallium/drivers/r600/r600_state_common.c
> +++ b/src/gallium/drivers/r600/r600_state_common.c
> @@ -966,6 +966,74 @@ static void r600_set_constant_buffer(struct
> pipe_context *ctx, uint shader, uint
> r600_constant_buffers_dirty(rctx, state);
> }
>
> +void r600_atomic_buffers_dirty(struct r600_context *rctx, struct
> r600_atombuf_state *state)
> +{
> + if (state->dirty_mask) {
> + rctx->b.flags |= R600_CONTEXT_INV_ATOM_CACHE;
> + state->atom.num_dw = rctx->b.chip_class >= EVERGREEN ?
> util_bitcount(state->dirty_mask)*20 : util_bitcount(state->dirty_mask) * 19;
> + state->atom.dirty = true;
> + }
> +}
> +
> +static void r600_set_atomic_buffer(struct pipe_context *ctx, uint shader,
> uint index,
> +
> struct pipe_surface *input)
> +{
> + struct r600_context *rctx = (struct r600_context *)ctx;
> + struct r600_atombuf_state *state = &rctx->atombuf_state[shader];
> + struct pipe_surface *surf;
> +
> + state->surf = r600_create_surface(ctx, input->texture , input);
> +
> +/* The code below represent Atomic buffers as a buffer.
> + In our implementation we bind atomic buffers to texture so that
> + it can be reused for image_load_store
> +
> + if(unlikely(!input || (!input->texture))){
> + state->enabled_mask &= ~(1 << index);
> + state->dirty_mask &= ~(1 << index);
> + pipe_resource_reference(&state->ab[index].texture, NULL);
> + return;
> + }
> +
> + ab = &state->ab[index];
> + ab->width = input->width;
> + ab->height = input->height;
> +
> + ptr = input->texture;
> + unsigned size = sizeof(unsigned)*input->height*input->width;
> +
> + if (ptr){
> + if(R600_BIG_ENDIAN) {
> + uint32_t *tmpPtr;
> + unsigned i;
> +
> + if (!(tmpPtr = malloc(size))) {
> + R600_ERR("Failed to allocate Atomic
> buffer\n");
> + return;
> + }
> +
> + for(i = 0; i < size / 4; ++i){
> + tmpPtr[i] = util_cpu_to_le32(((uint32_t
> *)ptr)[i]);
> + }
> +
> + // This can be changed as no need for data
> transfer. Offset can be changed
> + u_upload_data(rctx->b.uploader, 0, size, tmpPtr,
> &input->u.buf.first_element, &ab->texture);
> + free(tmpPtr);
> + } else {
> + u_upload_data(rctx->b.uploader, 0, size, ptr,
> &input->u.buf.first_element, &ab->texture);
> + }
> + rctx->b.gtt += size;
> + } else {
> + // cb->buffer_offset = input->buffer_offset;
> + pipe_resource_reference(&ab->texture, input->texture);
> + r600_context_add_resource_size(ctx, input->texture);
> + }
> +
> + state->enabled_mask |= 1 << index;
> + state->dirty_mask |= 1 << index;*/
> + r600_atomic_buffers_dirty(rctx, state);
> +}
> +
> static void r600_set_sample_mask(struct pipe_context *pipe, unsigned
> sample_mask)
> {
> struct r600_context *rctx = (struct r600_context*)pipe;
> @@ -2452,6 +2520,7 @@ void r600_init_common_state_functions(struct
> r600_context *rctx)
> rctx->b.b.set_blend_color = r600_set_blend_color;
> rctx->b.b.set_clip_state = r600_set_clip_state;
> rctx->b.b.set_constant_buffer = r600_set_constant_buffer;
> + rctx->b.b.set_atomic_buffer = r600_set_atomic_buffer;
> rctx->b.b.set_sample_mask = r600_set_sample_mask;
> rctx->b.b.set_stencil_ref = r600_set_pipe_stencil_ref;
> rctx->b.b.set_viewport_states = r600_set_viewport_states;
> diff --git a/src/gallium/drivers/r600/r600d.h
> b/src/gallium/drivers/r600/r600d.h
> index 6a5b964..1a2af8b 100644
> --- a/src/gallium/drivers/r600/r600d.h
> +++ b/src/gallium/drivers/r600/r600d.h
> @@ -3716,6 +3716,17 @@
> #define R_028984_ALU_CONST_CACHE_VS_1 0x00028984
> #define R_0289C0_ALU_CONST_CACHE_GS_0 0x000289C0
>
> +#define R_028200_ALU_ATOM_BUFFER_SIZE_PS_0 0x00028200
> +#define R_028204_ALU_ATOM_BUFFER_SIZE_PS_1 0x00028204
> +#define R_028240_ALU_ATOM_BUFFER_SIZE_VS_0 0x00028240
> +#define R_028244_ALU_ATOM_BUFFER_SIZE_VS_1 0x00028244
> +#define R_028280_ALU_ATOM_BUFFER_SIZE_GS_0 0x00028280
> +#define R_028A40_ALU_ATOM_CACHE_PS_0 0x00028A40
> +#define R_028A44_ALU_ATOM_CACHE_PS_1 0x00028A44
> +#define R_028A80_ALU_ATOM_CACHE_VS_0 0x00028A80
> +#define R_028A84_ALU_ATOM_CACHE_VS_1 0x00028A84
> +#define R_028AC0_ALU_ATOM_CACHE_GS_0 0x00028AC0
> +
> #define R_03CFF0_SQ_VTX_BASE_VTX_LOC 0x03CFF0
> #define R_03CFF4_SQ_VTX_START_INST_LOC 0x03CFF4
>
> diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c
> b/src/gallium/drivers/radeon/r600_pipe_common.c
> index 8aad178..6c5e1a4 100644
> --- a/src/gallium/drivers/radeon/r600_pipe_common.c
> +++ b/src/gallium/drivers/radeon/r600_pipe_common.c
> @@ -233,7 +233,7 @@ bool r600_common_context_init(struct
> r600_common_context *rctx,
>
> rctx->uploader = u_upload_create(&rctx->b, 1024 * 1024, 256,
> PIPE_BIND_INDEX_BUFFER |
> - PIPE_BIND_CONSTANT_BUFFER);
> + PIPE_BIND_CONSTANT_BUFFER |
> PIPE_BIND_ATOMIC_BUFFER);
> if (!rctx->uploader)
> return false;
>
> --
> 1.9.1
>
>
--
Regards,
*Aditya Atluri,*
*USA.*
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20150105/f23f6ef8/attachment-0001.html>
More information about the mesa-dev
mailing list