[Mesa-dev] [PATCH 4/4] softpipe: add SSBO/shader atomics support.
Brian Paul
brianp at vmware.com
Mon Apr 11 15:05:35 UTC 2016
I did a quite read-through. Just minor nit-picks below.
Otherwise, Reviewed-by: Brian Paul <brianp at vmware.com>
On 04/10/2016 09:20 PM, Dave Airlie wrote:
> From: Dave Airlie <airlied at redhat.com>
>
> This adds support for the features requires for ARB_shader_storage_buffer_object
> and ARB_shader_atomic_counters, ARB_shader_atomic_counter_ops.
>
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> ---
> docs/GL3.txt | 8 +-
> docs/relnotes/11.3.0.html | 4 +-
> src/gallium/auxiliary/tgsi/tgsi_exec.h | 3 +-
> src/gallium/drivers/softpipe/Makefile.sources | 1 +
> src/gallium/drivers/softpipe/sp_buffer.c | 376 ++++++++++++++++++++++++
> src/gallium/drivers/softpipe/sp_buffer.h | 37 +++
> src/gallium/drivers/softpipe/sp_context.c | 15 +
> src/gallium/drivers/softpipe/sp_context.h | 2 +
> src/gallium/drivers/softpipe/sp_fs_exec.c | 5 +-
> src/gallium/drivers/softpipe/sp_screen.c | 3 +-
> src/gallium/drivers/softpipe/sp_state.h | 4 +-
> src/gallium/drivers/softpipe/sp_state_derived.c | 3 +-
> src/gallium/drivers/softpipe/sp_state_image.c | 28 ++
> 13 files changed, 478 insertions(+), 11 deletions(-)
> create mode 100644 src/gallium/drivers/softpipe/sp_buffer.c
> create mode 100644 src/gallium/drivers/softpipe/sp_buffer.h
>
> diff --git a/docs/GL3.txt b/docs/GL3.txt
> index e6bb752..0d65673 100644
> --- a/docs/GL3.txt
> +++ b/docs/GL3.txt
> @@ -150,7 +150,7 @@ GL 4.2, GLSL 4.20:
>
> GL_ARB_texture_compression_bptc DONE (i965, nvc0, r600, radeonsi)
> GL_ARB_compressed_texture_pixel_storage DONE (all drivers)
> - GL_ARB_shader_atomic_counters DONE (i965, nvc0)
> + GL_ARB_shader_atomic_counters DONE (i965, nvc0, softpipe)
> GL_ARB_texture_storage DONE (all drivers)
> GL_ARB_transform_feedback_instanced DONE (i965, nv50, nvc0, r600, radeonsi, llvmpipe, softpipe)
> GL_ARB_base_instance DONE (i965, nv50, nvc0, r600, radeonsi, llvmpipe, softpipe)
> @@ -179,7 +179,7 @@ GL 4.3, GLSL 4.30:
> GL_ARB_program_interface_query DONE (all drivers)
> GL_ARB_robust_buffer_access_behavior not started
> GL_ARB_shader_image_size DONE (i965, radeonsi, softpipe)
> - GL_ARB_shader_storage_buffer_object DONE (i965, nvc0)
> + GL_ARB_shader_storage_buffer_object DONE (i965, nvc0, softpipe)
> GL_ARB_stencil_texturing DONE (i965/gen8+, nv50, nvc0, r600, radeonsi, llvmpipe, softpipe)
> GL_ARB_texture_buffer_range DONE (nv50, nvc0, i965, r600, radeonsi, llvmpipe)
> GL_ARB_texture_query_levels DONE (all drivers that support GLSL 1.30)
> @@ -230,10 +230,10 @@ GLES3.1, GLSL ES 3.1
> GL_ARB_explicit_uniform_location DONE (all drivers that support GLSL)
> GL_ARB_framebuffer_no_attachments DONE (i965, nvc0, r600, radeonsi)
> GL_ARB_program_interface_query DONE (all drivers)
> - GL_ARB_shader_atomic_counters DONE (i965, nvc0)
> + GL_ARB_shader_atomic_counters DONE (i965, nvc0, softpipe)
> GL_ARB_shader_image_load_store DONE (i965, softpipe)
> GL_ARB_shader_image_size DONE (i965, softpipe)
> - GL_ARB_shader_storage_buffer_object DONE (i965, nvc0)
> + GL_ARB_shader_storage_buffer_object DONE (i965, nvc0, softpipe)
> GL_ARB_shading_language_packing DONE (all drivers)
> GL_ARB_separate_shader_objects DONE (all drivers)
> GL_ARB_stencil_texturing DONE (i965/gen8+, nv50, nvc0, r600, radeonsi, llvmpipe, softpipe)
> diff --git a/docs/relnotes/11.3.0.html b/docs/relnotes/11.3.0.html
> index 97c83a3..8cdbc92 100644
> --- a/docs/relnotes/11.3.0.html
> +++ b/docs/relnotes/11.3.0.html
> @@ -46,9 +46,11 @@ Note: some of the new features are only available with certain drivers.
> <ul>
> <li>GL_ARB_framebuffer_no_attachments on nvc0, r600, radeonsi</li>
> <li>GL_ARB_internalformat_query2 on all drivers</li>
> -<li>GL_ARB_shader_atomic_counter_ops on nvc0</li>
> +<li>GL_ARB_shader_atomic_counters on softpipe</li>
> +<li>GL_ARB_shader_atomic_counter_ops on nvc0, softpipe</li>
> <li>GL_ARB_shader_image_load_store on radeonsi, softpipe</li>
> <li>GL_ARB_shader_image_size on radeonsi, softpipe</li>
> +<li>GL_ARB_shader_storage_buffer_objects on softpipe</li>
> <li>GL_ATI_fragment_shader on all Gallium drivers</li>
> <li>GL_EXT_base_instance on all drivers that support GL_ARB_base_instance</li>
> <li>GL_OES_draw_buffers_indexed and GL_EXT_draw_buffers_indexed on all drivers that support GL_ARB_draw_buffers_blend</li>
> diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h
> index 257c58f..42fb922 100644
> --- a/src/gallium/auxiliary/tgsi/tgsi_exec.h
> +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h
> @@ -528,8 +528,9 @@ tgsi_exec_get_shader_param(enum pipe_shader_cap param)
> return 1;
> case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED:
> case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED:
> - case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:
> return 0;
> + case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS:
> + return PIPE_MAX_SHADER_BUFFERS;
> case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:
> return PIPE_MAX_SHADER_IMAGES;
>
> diff --git a/src/gallium/drivers/softpipe/Makefile.sources b/src/gallium/drivers/softpipe/Makefile.sources
> index efe8846..97e37d7 100644
> --- a/src/gallium/drivers/softpipe/Makefile.sources
> +++ b/src/gallium/drivers/softpipe/Makefile.sources
> @@ -1,4 +1,5 @@
> C_SOURCES := \
> + sp_buffer.c \
> sp_clear.c \
> sp_clear.h \
> sp_context.c \
> diff --git a/src/gallium/drivers/softpipe/sp_buffer.c b/src/gallium/drivers/softpipe/sp_buffer.c
> new file mode 100644
> index 0000000..f9b3e1f
> --- /dev/null
> +++ b/src/gallium/drivers/softpipe/sp_buffer.c
> @@ -0,0 +1,376 @@
> +/*
> + * Copyright 2016 Red Hat.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * on the rights to use, copy, modify, merge, publish, distribute, sub
> + * license, and/or sell copies of the Software, and to permit persons to whom
> + * the Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
> + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
> + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
> + * USE OR OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +#include "sp_context.h"
> +#include "sp_buffer.h"
> +#include "sp_texture.h"
> +
> +#include "util/u_format.h"
> +
> +static bool
> +get_dimensions(const struct pipe_shader_buffer *bview,
> + const struct softpipe_resource *spr,
> + unsigned *width)
> +{
> + *width = bview->buffer_size;
> + /*
> + * Bounds check the buffer size from the view
> + * and the buffer size from the underlying buffer.
> + */
> + if (*width > spr->base.width0)
> + return false;
> + return true;
> +}
> +
> +/*
> + * Implement the image LOAD operation.
> + */
> +static void
> +sp_tgsi_load(const struct tgsi_buffer *buffer,
> + const struct tgsi_buffer_params *params,
> + const int s[TGSI_QUAD_SIZE],
> + float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
> +{
> + struct sp_tgsi_buffer *sp_buf = (struct sp_tgsi_buffer *)buffer;
> + struct pipe_shader_buffer *bview;
> + struct softpipe_resource *spr;
> + unsigned width;
> + int c, j;
> + unsigned char *data_ptr;
> + const struct util_format_description *format_desc = util_format_description(PIPE_FORMAT_R32_UINT);
> +
> + if (params->unit > PIPE_MAX_SHADER_BUFFERS)
> + goto fail_write_all_zero;
> +
> + bview = &sp_buf->sp_bview[params->unit];
> + spr = (struct softpipe_resource *)bview->buffer;
> + if (!spr)
> + goto fail_write_all_zero;
> +
> + if (!get_dimensions(bview, spr, &width))
> + return;
> +
> + for (j = 0; j < TGSI_QUAD_SIZE; j++) {
> + int s_coord;
> + bool fill_zero = false;
> + uint32_t sdata[4];
> +
> + if (!(params->execmask & (1 << j)))
> + fill_zero = true;
> +
> + s_coord = s[j];
> + if (s_coord >= width)
> + fill_zero = true;
> +
> + if (fill_zero) {
> + for (c = 0; c < 4; c++)
> + rgba[c][j] = 0;
> + continue;
> + }
> + data_ptr = (unsigned char *)spr->data + bview->buffer_offset + s_coord;
> + for (c = 0; c < 4; c++) {
> + format_desc->fetch_rgba_uint(sdata, data_ptr, 0, 0);
> + ((uint32_t *)rgba[c])[j] = sdata[0];
> + data_ptr += 4;
> + }
> + }
> + return;
> +fail_write_all_zero:
> + for (j = 0; j < TGSI_QUAD_SIZE; j++) {
> + for (c = 0; c < 4; c++)
> + rgba[c][j] = 0;
> + }
> + return;
> +}
> +
> +/*
> + * Implement the buffer STORE operation.
> + */
> +static void
> +sp_tgsi_store(const struct tgsi_buffer *buffer,
> + const struct tgsi_buffer_params *params,
> + const int s[TGSI_QUAD_SIZE],
> + float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
> +{
> + struct sp_tgsi_buffer *sp_buf = (struct sp_tgsi_buffer *)buffer;
> + struct pipe_shader_buffer *bview;
> + struct softpipe_resource *spr;
> + unsigned width;
> + unsigned char *data_ptr;
> + int j, c;
> + const struct util_format_description *format_desc = util_format_description(PIPE_FORMAT_R32_UINT);
> +
> + if (params->unit > PIPE_MAX_SHADER_BUFFERS)
> + return;
> +
> + bview = &sp_buf->sp_bview[params->unit];
> + spr = (struct softpipe_resource *)bview->buffer;
I see this cast quite a bit. Maybe use an inline cast wrapper?
> + if (!spr)
> + return;
> +
> + if (!get_dimensions(bview, spr, &width))
> + return;
> +
> + for (j = 0; j < TGSI_QUAD_SIZE; j++) {
> + int s_coord;
> +
> + if (!(params->execmask & (1 << j)))
> + continue;
> +
> + s_coord = s[j];
> + if (s_coord >= width)
> + continue;
> +
> + data_ptr = (unsigned char *)spr->data + bview->buffer_offset + s_coord;
> +
> + for (c = 0; c < 4; c++) {
> + if (params->writemask & (1 << c)) {
> + unsigned temp[4];
> + unsigned char *dptr = data_ptr + (c * 4);
> + temp[0] = ((uint32_t *)rgba[c])[j];
> + format_desc->pack_rgba_uint(dptr, 0, temp, 0, 1, 1);
> + }
> + }
> + }
> +}
> +
> +/*
> + * Implement atomic operations on unsigned integers.
> + */
> +static void
> +handle_op_uint(const struct pipe_shader_buffer *bview,
> + bool just_read,
> + unsigned char *data_ptr,
> + uint qi,
> + unsigned opcode,
> + unsigned writemask,
> + float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
> + float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
> +{
> + uint c;
> + const struct util_format_description *format_desc = util_format_description(PIPE_FORMAT_R32_UINT);
> + unsigned sdata[4];
> +
> + for (c = 0; c < 4; c++) {
> + unsigned temp[4];
> + unsigned char *dptr = data_ptr + (c * 4);
> + format_desc->fetch_rgba_uint(temp, dptr, 0, 0);
> + sdata[c] = temp[0];
> + }
> +
> + if (just_read) {
> + for (c = 0; c < 4; c++) {
> + ((uint32_t *)rgba[c])[qi] = sdata[c];
> + }
> + return;
> + }
> +
> + switch (opcode) {
> + case TGSI_OPCODE_ATOMUADD:
> + for (c = 0; c < 4; c++) {
> + unsigned temp = sdata[c];
> + sdata[c] += ((uint32_t *)rgba[c])[qi];
> + ((uint32_t *)rgba[c])[qi] = temp;
> + }
> + break;
> + case TGSI_OPCODE_ATOMXCHG:
> + for (c = 0; c < 4; c++) {
> + unsigned temp = sdata[c];
> + sdata[c] = ((uint32_t *)rgba[c])[qi];
> + ((uint32_t *)rgba[c])[qi] = temp;
> + }
> + break;
> + case TGSI_OPCODE_ATOMCAS:
> + for (c = 0; c < 4; c++) {
> + unsigned dst_x = sdata[c];
> + unsigned cmp_x = ((uint32_t *)rgba[c])[qi];
> + unsigned src_x = ((uint32_t *)rgba2[c])[qi];
> + unsigned temp = sdata[c];
> + sdata[c] = (dst_x == cmp_x) ? src_x : dst_x;
> + ((uint32_t *)rgba[c])[qi] = temp;
> + }
> + break;
> + case TGSI_OPCODE_ATOMAND:
> + for (c = 0; c < 4; c++) {
> + unsigned temp = sdata[c];
> + sdata[c] &= ((uint32_t *)rgba[c])[qi];
> + ((uint32_t *)rgba[c])[qi] = temp;
> + }
> + break;
> + case TGSI_OPCODE_ATOMOR:
> + for (c = 0; c < 4; c++) {
> + unsigned temp = sdata[c];
> + sdata[c] |= ((uint32_t *)rgba[c])[qi];
> + ((uint32_t *)rgba[c])[qi] = temp;
> + }
> + break;
> + case TGSI_OPCODE_ATOMXOR:
> + for (c = 0; c < 4; c++) {
> + unsigned temp = sdata[c];
> + sdata[c] ^= ((uint32_t *)rgba[c])[qi];
> + ((uint32_t *)rgba[c])[qi] = temp;
> + }
> + break;
> + case TGSI_OPCODE_ATOMUMIN:
> + for (c = 0; c < 4; c++) {
> + unsigned dst_x = sdata[c];
> + unsigned src_x = ((uint32_t *)rgba[c])[qi];
> + sdata[c] = MIN2(dst_x, src_x);
> + ((uint32_t *)rgba[c])[qi] = dst_x;
> + }
> + break;
> + case TGSI_OPCODE_ATOMUMAX:
> + for (c = 0; c < 4; c++) {
> + unsigned dst_x = sdata[c];
> + unsigned src_x = ((uint32_t *)rgba[c])[qi];
> + sdata[c] = MAX2(dst_x, src_x);
> + ((uint32_t *)rgba[c])[qi] = dst_x;
> + }
> + break;
> + case TGSI_OPCODE_ATOMIMIN:
> + for (c = 0; c < 4; c++) {
> + int dst_x = sdata[c];
> + int src_x = ((uint32_t *)rgba[c])[qi];
> + sdata[c] = MIN2(dst_x, src_x);
> + ((uint32_t *)rgba[c])[qi] = dst_x;
> + }
> + break;
> + case TGSI_OPCODE_ATOMIMAX:
> + for (c = 0; c < 4; c++) {
> + int dst_x = sdata[c];
> + int src_x = ((uint32_t *)rgba[c])[qi];
> + sdata[c] = MAX2(dst_x, src_x);
> + ((uint32_t *)rgba[c])[qi] = dst_x;
> + }
> + break;
> + default:
> + assert(!"Unexpected TGSI opcode in sp_tgsi_op");
> + break;
> + }
> +
> + for (c = 0; c < 4; c++) {
> + if (writemask & (1 << c)) {
> + unsigned temp[4];
> + unsigned char *dptr = data_ptr + (c * 4);
> + temp[0] = sdata[c];
> + format_desc->pack_rgba_uint(dptr, 0, temp, 0, 1, 1);
> + }
> + }
> +}
> +
> +/*
> + * Implement atomic buffer operations.
> + */
> +static void
> +sp_tgsi_op(const struct tgsi_buffer *buffer,
> + const struct tgsi_buffer_params *params,
> + unsigned opcode,
> + const int s[TGSI_QUAD_SIZE],
> + float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
> + float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
> +{
> + struct sp_tgsi_buffer *sp_buf = (struct sp_tgsi_buffer *)buffer;
> + struct pipe_shader_buffer *bview;
> + struct softpipe_resource *spr;
> + unsigned width;
> + int j, c;
> + unsigned char *data_ptr;
> +
> + if (params->unit > PIPE_MAX_SHADER_BUFFERS)
> + return;
> +
> + bview = &sp_buf->sp_bview[params->unit];
> + spr = (struct softpipe_resource *)bview->buffer;
> + if (!spr)
> + goto fail_write_all_zero;
> +
> + if (!get_dimensions(bview, spr,
> + &width))
That could go on one line.
> + goto fail_write_all_zero;
> +
> + for (j = 0; j < TGSI_QUAD_SIZE; j++) {
> + int s_coord;
> + bool just_read = false;
> +
> + s_coord = s[j];
> + if (s_coord >= width) {
> + int c;
> + for (c = 0; c < 4; c++) {
> + rgba[c][j] = 0;
> + }
> + continue;
> + }
> +
> + /* just readback the value for atomic if execmask isn't set */
> + if (!(params->execmask & (1 << j))) {
> + just_read = true;
> + }
> +
> + data_ptr = (unsigned char *)spr->data + bview->buffer_offset + s_coord;
> + /* we should see atomic operations on r32 formats */
> +
> + handle_op_uint(bview, just_read, data_ptr, j,
> + opcode, params->writemask, rgba, rgba2);
> + }
> + return;
> +fail_write_all_zero:
> + for (j = 0; j < TGSI_QUAD_SIZE; j++) {
> + for (c = 0; c < 4; c++)
> + rgba[c][j] = 0;
> + }
just memset instead?
> + return;
> +}
> +
> +static void
> +sp_tgsi_get_dims(const struct tgsi_buffer *buffer,
> + const struct tgsi_buffer_params *params,
> + int *dim)
Maybe add a comment on this function to explain what it's doing?
> +{
> + struct sp_tgsi_buffer *sp_buf = (struct sp_tgsi_buffer *)buffer;
> + struct pipe_shader_buffer *bview;
> + struct softpipe_resource *spr;
> +
> + if (params->unit > PIPE_MAX_SHADER_BUFFERS)
> + return;
> +
> + bview = &sp_buf->sp_bview[params->unit];
> + spr = (struct softpipe_resource *)bview->buffer;
> + if (!spr)
> + return;
> +
> + *dim = bview->buffer_size;
> +}
> +
> +struct sp_tgsi_buffer *
> +sp_create_tgsi_buffer(void)
> +{
> + struct sp_tgsi_buffer *buf = CALLOC_STRUCT(sp_tgsi_buffer);
> + if (!buf)
> + return NULL;
> +
> + buf->base.load = sp_tgsi_load;
> + buf->base.store = sp_tgsi_store;
> + buf->base.op = sp_tgsi_op;
> + buf->base.get_dims = sp_tgsi_get_dims;
> + return buf;
> +};
> diff --git a/src/gallium/drivers/softpipe/sp_buffer.h b/src/gallium/drivers/softpipe/sp_buffer.h
> new file mode 100644
> index 0000000..1822fe7
> --- /dev/null
> +++ b/src/gallium/drivers/softpipe/sp_buffer.h
> @@ -0,0 +1,37 @@
> +/*
> + * Copyright 2016 Red Hat.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * on the rights to use, copy, modify, merge, publish, distribute, sub
> + * license, and/or sell copies of the Software, and to permit persons to whom
> + * the Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
> + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
> + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
> + * USE OR OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +#ifndef SP_BUFFER_H
> +#define SP_BUFFER_H
> +#include "tgsi/tgsi_exec.h"
> +
> +struct sp_tgsi_buffer
> +{
> + struct tgsi_buffer base;
> + struct pipe_shader_buffer sp_bview[PIPE_MAX_SHADER_BUFFERS];
> +};
> +
> +struct sp_tgsi_buffer *
> +sp_create_tgsi_buffer(void);
> +
> +#endif
> diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c
> index 30b0276..f66fea2 100644
> --- a/src/gallium/drivers/softpipe/sp_context.c
> +++ b/src/gallium/drivers/softpipe/sp_context.c
> @@ -38,6 +38,7 @@
> #include "util/u_pstipple.h"
> #include "util/u_inlines.h"
> #include "tgsi/tgsi_exec.h"
> +#include "sp_buffer.h"
> #include "sp_clear.h"
> #include "sp_context.h"
> #include "sp_flush.h"
> @@ -203,6 +204,10 @@ softpipe_create_context(struct pipe_screen *screen,
> softpipe->tgsi.image[i] = sp_create_tgsi_image();
> }
>
> + for (i = 0; i < PIPE_SHADER_TYPES; i++) {
> + softpipe->tgsi.buffer[i] = sp_create_tgsi_buffer();
> + }
> +
> softpipe->dump_fs = debug_get_bool_option( "SOFTPIPE_DUMP_FS", FALSE );
> softpipe->dump_gs = debug_get_bool_option( "SOFTPIPE_DUMP_GS", FALSE );
>
> @@ -288,6 +293,16 @@ softpipe_create_context(struct pipe_screen *screen,
> (struct tgsi_image *)
> softpipe->tgsi.image[PIPE_SHADER_GEOMETRY]);
>
> + draw_buffer(softpipe->draw,
> + PIPE_SHADER_VERTEX,
> + (struct tgsi_buffer *)
> + softpipe->tgsi.buffer[PIPE_SHADER_VERTEX]);
> +
> + draw_buffer(softpipe->draw,
> + PIPE_SHADER_GEOMETRY,
> + (struct tgsi_buffer *)
> + softpipe->tgsi.buffer[PIPE_SHADER_GEOMETRY]);
> +
> if (debug_get_bool_option( "SOFTPIPE_NO_RAST", FALSE ))
> softpipe->no_rast = TRUE;
>
> diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h
> index 20a1235..70d00c8 100644
> --- a/src/gallium/drivers/softpipe/sp_context.h
> +++ b/src/gallium/drivers/softpipe/sp_context.h
> @@ -84,6 +84,7 @@ struct softpipe_context {
> struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
>
> struct pipe_image_view images[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_IMAGES];
> + struct pipe_shader_buffer buffers[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_BUFFERS];
> struct pipe_viewport_state viewports[PIPE_MAX_VIEWPORTS];
> struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
> struct pipe_index_buffer index_buffer;
> @@ -174,6 +175,7 @@ struct softpipe_context {
> struct {
> struct sp_tgsi_sampler *sampler[PIPE_SHADER_TYPES];
> struct sp_tgsi_image *image[PIPE_SHADER_TYPES];
> + struct sp_tgsi_buffer *buffer[PIPE_SHADER_TYPES];
> } tgsi;
>
> struct tgsi_exec_machine *fs_machine;
> diff --git a/src/gallium/drivers/softpipe/sp_fs_exec.c b/src/gallium/drivers/softpipe/sp_fs_exec.c
> index 6a5f7ac..155382a 100644
> --- a/src/gallium/drivers/softpipe/sp_fs_exec.c
> +++ b/src/gallium/drivers/softpipe/sp_fs_exec.c
> @@ -63,14 +63,15 @@ static void
> exec_prepare( const struct sp_fragment_shader_variant *var,
> struct tgsi_exec_machine *machine,
> struct tgsi_sampler *sampler,
> - struct tgsi_image *image )
> + struct tgsi_image *image,
> + struct tgsi_buffer *buffer )
> {
> /*
> * Bind tokens/shader to the interpreter's machine state.
> */
> tgsi_exec_machine_bind_shader(machine,
> var->tokens,
> - sampler, image, NULL);
> + sampler, image, buffer);
> }
>
>
> diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
> index 90f29d6..00b414c 100644
> --- a/src/gallium/drivers/softpipe/sp_screen.c
> +++ b/src/gallium/drivers/softpipe/sp_screen.c
> @@ -259,7 +259,6 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
> case PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS:
> case PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL:
> case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL:
> - case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT:
> case PIPE_CAP_INVALIDATE_BUFFER:
> case PIPE_CAP_GENERATE_MIPMAP:
> case PIPE_CAP_STRING_MARKER:
> @@ -272,6 +271,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
> case PIPE_CAP_PCI_FUNCTION:
> case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT:
> return 0;
> + case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT:
> + return 4;
> }
> /* should only get here on unhandled cases */
> debug_printf("Unexpected PIPE_CAP %d query\n", param);
> diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h
> index 570bc54..2fc48ab 100644
> --- a/src/gallium/drivers/softpipe/sp_state.h
> +++ b/src/gallium/drivers/softpipe/sp_state.h
> @@ -57,6 +57,7 @@
>
> struct tgsi_sampler;
> struct tgsi_image;
> +struct tgsi_buffer;
> struct tgsi_exec_machine;
> struct vertex_info;
>
> @@ -83,7 +84,8 @@ struct sp_fragment_shader_variant
> void (*prepare)(const struct sp_fragment_shader_variant *shader,
> struct tgsi_exec_machine *machine,
> struct tgsi_sampler *sampler,
> - struct tgsi_image *image);
> + struct tgsi_image *image,
> + struct tgsi_buffer *buffer);
>
> unsigned (*run)(const struct sp_fragment_shader_variant *shader,
> struct tgsi_exec_machine *machine,
> diff --git a/src/gallium/drivers/softpipe/sp_state_derived.c b/src/gallium/drivers/softpipe/sp_state_derived.c
> index 65679e7..4ce9d95 100644
> --- a/src/gallium/drivers/softpipe/sp_state_derived.c
> +++ b/src/gallium/drivers/softpipe/sp_state_derived.c
> @@ -344,7 +344,8 @@ update_fragment_shader(struct softpipe_context *softpipe, unsigned prim)
> softpipe->fs_machine,
> (struct tgsi_sampler *) softpipe->
> tgsi.sampler[PIPE_SHADER_FRAGMENT],
> - (struct tgsi_image *)softpipe->tgsi.image[PIPE_SHADER_FRAGMENT]);
> + (struct tgsi_image *)softpipe->tgsi.image[PIPE_SHADER_FRAGMENT],
> + (struct tgsi_buffer *)softpipe->tgsi.buffer[PIPE_SHADER_FRAGMENT]);
> }
> else {
> softpipe->fs_variant = NULL;
> diff --git a/src/gallium/drivers/softpipe/sp_state_image.c b/src/gallium/drivers/softpipe/sp_state_image.c
> index 8909fa2..5947c93 100644
> --- a/src/gallium/drivers/softpipe/sp_state_image.c
> +++ b/src/gallium/drivers/softpipe/sp_state_image.c
> @@ -24,6 +24,7 @@
> #include "sp_context.h"
> #include "sp_state.h"
> #include "sp_image.h"
> +#include "sp_buffer.h"
>
> static void softpipe_set_shader_images(struct pipe_context *pipe,
> unsigned shader,
> @@ -51,7 +52,34 @@ static void softpipe_set_shader_images(struct pipe_context *pipe,
> }
> }
>
> +static void softpipe_set_shader_buffers(struct pipe_context *pipe,
> + unsigned shader,
> + unsigned start,
> + unsigned num,
> + struct pipe_shader_buffer *buffers)
> +{
> + struct softpipe_context *softpipe = softpipe_context(pipe);
> + unsigned i;
> + assert(shader < PIPE_SHADER_TYPES);
> + assert(start + num <= Elements(softpipe->buffers[shader]));
> +
> + /* set the new images */
> + for (i = 0; i < num; i++) {
> + int idx = start + i;
> +
> + if (buffers) {
> + pipe_resource_reference(&softpipe->tgsi.buffer[shader]->sp_bview[idx].buffer, buffers[i].buffer);
> + softpipe->tgsi.buffer[shader]->sp_bview[idx] = buffers[i];
> + }
> + else {
> + pipe_resource_reference(&softpipe->tgsi.buffer[shader]->sp_bview[idx].buffer, NULL);
> + memset(&softpipe->tgsi.buffer[shader]->sp_bview[idx], 0, sizeof(struct pipe_shader_buffer));
> + }
> + }
> +}
> +
> void softpipe_init_image_funcs(struct pipe_context *pipe)
> {
> pipe->set_shader_images = softpipe_set_shader_images;
> + pipe->set_shader_buffers = softpipe_set_shader_buffers;
> }
>
More information about the mesa-dev
mailing list