llvmpipe: add support for shader buffer binding.

This add support for setting shader buffers and passing them
to draw or binding them to the fragment shader jit.

Reviewed-by: Roland Scheidegger <sroland@vmware.com>
This commit is contained in:
Dave Airlie 2019-06-26 15:57:30 +10:00
parent d8fb66a3e1
commit df46b3d196
8 changed files with 100 additions and 2 deletions

View File

@ -82,6 +82,8 @@ struct llvmpipe_context {
struct pipe_viewport_state viewports[PIPE_MAX_VIEWPORTS];
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
struct pipe_shader_buffer ssbos[PIPE_SHADER_TYPES][LP_MAX_TGSI_SHADER_BUFFERS];
unsigned num_samplers[PIPE_SHADER_TYPES];
unsigned num_sampler_views[PIPE_SHADER_TYPES];

View File

@ -664,6 +664,26 @@ lp_setup_set_fs_constants(struct lp_setup_context *setup,
setup->dirty |= LP_SETUP_NEW_CONSTANTS;
}
void
lp_setup_set_fs_ssbos(struct lp_setup_context *setup,
unsigned num,
struct pipe_shader_buffer *buffers)
{
unsigned i;
LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffers);
assert(num <= ARRAY_SIZE(setup->ssbos));
for (i = 0; i < num; ++i) {
util_copy_shader_buffer(&setup->ssbos[i].current, &buffers[i]);
}
for (; i < ARRAY_SIZE(setup->ssbos); i++) {
util_copy_shader_buffer(&setup->ssbos[i].current, NULL);
}
setup->dirty |= LP_SETUP_NEW_SSBOS;
}
void
lp_setup_set_alpha_ref_value( struct lp_setup_context *setup,
@ -992,6 +1012,11 @@ lp_setup_is_resource_referenced( const struct lp_setup_context *setup,
}
}
for (i = 0; i < ARRAY_SIZE(setup->ssbos); i++) {
if (setup->ssbos[i].current.buffer == texture)
return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE;
}
return LP_UNREFERENCED;
}
@ -1135,7 +1160,27 @@ try_update_scene_state( struct lp_setup_context *setup )
}
}
if (setup->dirty & LP_SETUP_NEW_SSBOS) {
for (i = 0; i < ARRAY_SIZE(setup->ssbos); ++i) {
struct pipe_resource *buffer = setup->ssbos[i].current.buffer;
const ubyte *current_data = NULL;
if (!buffer)
continue;
/* resource buffer */
current_data = (ubyte *) llvmpipe_resource_data(buffer);
if (current_data) {
current_data += setup->ssbos[i].current.buffer_offset;
setup->fs.current.jit_context.ssbos[i] = (const uint32_t *)current_data;
setup->fs.current.jit_context.num_ssbos[i] = setup->ssbos[i].current.buffer_size;
} else {
setup->fs.current.jit_context.ssbos[i] = NULL;
setup->fs.current.jit_context.num_ssbos[i] = 0;
}
setup->dirty |= LP_SETUP_NEW_FS;
}
}
if (setup->dirty & LP_SETUP_NEW_FS) {
if (!setup->fs.stored ||
memcmp(setup->fs.stored,
@ -1287,6 +1332,10 @@ lp_setup_destroy( struct lp_setup_context *setup )
pipe_resource_reference(&setup->constants[i].current.buffer, NULL);
}
for (i = 0; i < ARRAY_SIZE(setup->ssbos); i++) {
pipe_resource_reference(&setup->ssbos[i].current.buffer, NULL);
}
/* free the scenes in the 'empty' queue */
for (i = 0; i < ARRAY_SIZE(setup->scenes); i++) {
struct lp_scene *scene = setup->scenes[i];

View File

@ -104,6 +104,11 @@ lp_setup_set_fs_constants(struct lp_setup_context *setup,
unsigned num,
struct pipe_constant_buffer *buffers);
void
lp_setup_set_fs_ssbos(struct lp_setup_context *setup,
unsigned num,
struct pipe_shader_buffer *buffers);
void
lp_setup_set_alpha_ref_value( struct lp_setup_context *setup,
float alpha_ref_value );

View File

@ -49,7 +49,7 @@
#define LP_SETUP_NEW_BLEND_COLOR 0x04
#define LP_SETUP_NEW_SCISSOR 0x08
#define LP_SETUP_NEW_VIEWPORTS 0x10
#define LP_SETUP_NEW_SSBOS 0x20
struct lp_setup_variant;
@ -143,6 +143,11 @@ struct lp_setup_context
const void *stored_data;
} constants[LP_MAX_TGSI_CONST_BUFFERS];
/** fragment shader buffers */
struct {
struct pipe_shader_buffer current;
} ssbos[LP_MAX_TGSI_SHADER_BUFFERS];
struct {
struct pipe_blend_color current;
uint8_t *stored;

View File

@ -56,6 +56,7 @@
#define LP_NEW_GS 0x10000
#define LP_NEW_SO 0x20000
#define LP_NEW_SO_BUFFERS 0x40000
#define LP_NEW_FS_SSBOS 0x80000

View File

@ -255,6 +255,11 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
ARRAY_SIZE(llvmpipe->constants[PIPE_SHADER_FRAGMENT]),
llvmpipe->constants[PIPE_SHADER_FRAGMENT]);
if (llvmpipe->dirty & LP_NEW_FS_SSBOS)
lp_setup_set_fs_ssbos(llvmpipe->setup,
ARRAY_SIZE(llvmpipe->ssbos[PIPE_SHADER_FRAGMENT]),
llvmpipe->ssbos[PIPE_SHADER_FRAGMENT]);
if (llvmpipe->dirty & (LP_NEW_SAMPLER_VIEW))
lp_setup_set_fragment_sampler_views(llvmpipe->setup,
llvmpipe->num_sampler_views[PIPE_SHADER_FRAGMENT],

View File

@ -3141,6 +3141,34 @@ llvmpipe_set_constant_buffer(struct pipe_context *pipe,
}
}
static void
llvmpipe_set_shader_buffers(struct pipe_context *pipe,
enum pipe_shader_type shader, unsigned start_slot,
unsigned count, const struct pipe_shader_buffer *buffers,
unsigned writable_bitmask)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
unsigned i, idx;
for (i = start_slot, idx = 0; i < start_slot + count; i++, idx++) {
const struct pipe_shader_buffer *buffer = buffers ? &buffers[idx] : NULL;
util_copy_shader_buffer(&llvmpipe->ssbos[shader][i], buffer);
if (shader == PIPE_SHADER_VERTEX ||
shader == PIPE_SHADER_GEOMETRY) {
const unsigned size = buffer ? buffer->buffer_size : 0;
const ubyte *data = NULL;
if (buffer && buffer->buffer)
data = (ubyte *) llvmpipe_resource_data(buffer->buffer);
if (data)
data += buffer->buffer_offset;
draw_set_mapped_shader_buffer(llvmpipe->draw, shader,
i, data, size);
} else if (shader == PIPE_SHADER_FRAGMENT) {
llvmpipe->dirty |= LP_NEW_FS_SSBOS;
}
}
}
/**
* Return the blend factor equivalent to a destination alpha of one.
@ -3484,6 +3512,8 @@ llvmpipe_init_fs_funcs(struct llvmpipe_context *llvmpipe)
llvmpipe->pipe.delete_fs_state = llvmpipe_delete_fs_state;
llvmpipe->pipe.set_constant_buffer = llvmpipe_set_constant_buffer;
llvmpipe->pipe.set_shader_buffers = llvmpipe_set_shader_buffers;
}

View File

@ -646,7 +646,8 @@ llvmpipe_is_resource_referenced( struct pipe_context *pipe,
struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
if (!(presource->bind & (PIPE_BIND_DEPTH_STENCIL |
PIPE_BIND_RENDER_TARGET |
PIPE_BIND_SAMPLER_VIEW)))
PIPE_BIND_SAMPLER_VIEW |
PIPE_BIND_SHADER_BUFFER)))
return LP_UNREFERENCED;
return lp_setup_is_resource_referenced(llvmpipe->setup, presource);