diff options
author | Dave Airlie <[email protected]> | 2016-04-11 13:02:20 +1000 |
---|---|---|
committer | Dave Airlie <[email protected]> | 2016-04-12 14:16:13 +1000 |
commit | afa8707ba93a7d226a76319acda2a8dd89524db7 (patch) | |
tree | 1e866666402a7b6b2bcc99529eec3a7b11783be4 /src | |
parent | c2aeeca4554d744b6293ad87d9a183e51b0138ff (diff) |
softpipe: add SSBO/shader atomics support.
This adds support for the features requires for ARB_shader_storage_buffer_object
and ARB_shader_atomic_counters, ARB_shader_atomic_counter_ops.
[airlied: some cleanups applied]
Reviewed-by: Brian Paul <[email protected]>
Reviewed-by: Roland Scheidegger <[email protected]>
Signed-off-by: Dave Airlie <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/auxiliary/tgsi/tgsi_exec.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/softpipe/Makefile.sources | 1 | ||||
-rw-r--r-- | src/gallium/drivers/softpipe/sp_buffer.c | 371 | ||||
-rw-r--r-- | src/gallium/drivers/softpipe/sp_buffer.h | 37 | ||||
-rw-r--r-- | src/gallium/drivers/softpipe/sp_context.c | 15 | ||||
-rw-r--r-- | src/gallium/drivers/softpipe/sp_context.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/softpipe/sp_fs_exec.c | 5 | ||||
-rw-r--r-- | src/gallium/drivers/softpipe/sp_screen.c | 3 | ||||
-rw-r--r-- | src/gallium/drivers/softpipe/sp_state.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/softpipe/sp_state_derived.c | 3 | ||||
-rw-r--r-- | src/gallium/drivers/softpipe/sp_state_image.c | 28 |
11 files changed, 466 insertions, 6 deletions
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h index 257c58f777e..42fb922baa5 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 3669dfc71f8..1d42351f975 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 00000000000..69717baa1a0 --- /dev/null +++ b/src/gallium/drivers/softpipe/sp_buffer.c @@ -0,0 +1,371 @@ +/* + * 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 = 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: + memset(rgba, 0, TGSI_NUM_CHANNELS * TGSI_QUAD_SIZE * 4); + 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 = softpipe_resource(bview->buffer); + 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 = softpipe_resource(bview->buffer); + if (!spr) + goto fail_write_all_zero; + + if (!get_dimensions(bview, spr, &width)) + 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) { + 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: + memset(rgba, 0, TGSI_NUM_CHANNELS * TGSI_QUAD_SIZE * 4); + return; +} + +/* + * return size of the attached buffer for RESQ opcode. + */ +static void +sp_tgsi_get_dims(const struct tgsi_buffer *buffer, + const struct tgsi_buffer_params *params, + int *dim) +{ + 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 = 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 00000000000..1822fe709fe --- /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 30b0276cfe0..f66fea2d5d5 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 20a12353b38..70d00c88b6e 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 6a5f7acd263..155382af825 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 90f29d6e52a..00b414cea9d 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 570bc549cc4..2fc48ab13d8 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 65679e73515..4ce9d95bc6e 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 8909fa26864..5947c934e86 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; } |