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:
parent
d8fb66a3e1
commit
df46b3d196
|
@ -82,6 +82,8 @@ struct llvmpipe_context {
|
||||||
struct pipe_viewport_state viewports[PIPE_MAX_VIEWPORTS];
|
struct pipe_viewport_state viewports[PIPE_MAX_VIEWPORTS];
|
||||||
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
|
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_samplers[PIPE_SHADER_TYPES];
|
||||||
unsigned num_sampler_views[PIPE_SHADER_TYPES];
|
unsigned num_sampler_views[PIPE_SHADER_TYPES];
|
||||||
|
|
||||||
|
|
|
@ -664,6 +664,26 @@ lp_setup_set_fs_constants(struct lp_setup_context *setup,
|
||||||
setup->dirty |= LP_SETUP_NEW_CONSTANTS;
|
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
|
void
|
||||||
lp_setup_set_alpha_ref_value( struct lp_setup_context *setup,
|
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;
|
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->dirty & LP_SETUP_NEW_FS) {
|
||||||
if (!setup->fs.stored ||
|
if (!setup->fs.stored ||
|
||||||
memcmp(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);
|
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 */
|
/* free the scenes in the 'empty' queue */
|
||||||
for (i = 0; i < ARRAY_SIZE(setup->scenes); i++) {
|
for (i = 0; i < ARRAY_SIZE(setup->scenes); i++) {
|
||||||
struct lp_scene *scene = setup->scenes[i];
|
struct lp_scene *scene = setup->scenes[i];
|
||||||
|
|
|
@ -104,6 +104,11 @@ lp_setup_set_fs_constants(struct lp_setup_context *setup,
|
||||||
unsigned num,
|
unsigned num,
|
||||||
struct pipe_constant_buffer *buffers);
|
struct pipe_constant_buffer *buffers);
|
||||||
|
|
||||||
|
void
|
||||||
|
lp_setup_set_fs_ssbos(struct lp_setup_context *setup,
|
||||||
|
unsigned num,
|
||||||
|
struct pipe_shader_buffer *buffers);
|
||||||
|
|
||||||
void
|
void
|
||||||
lp_setup_set_alpha_ref_value( struct lp_setup_context *setup,
|
lp_setup_set_alpha_ref_value( struct lp_setup_context *setup,
|
||||||
float alpha_ref_value );
|
float alpha_ref_value );
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
#define LP_SETUP_NEW_BLEND_COLOR 0x04
|
#define LP_SETUP_NEW_BLEND_COLOR 0x04
|
||||||
#define LP_SETUP_NEW_SCISSOR 0x08
|
#define LP_SETUP_NEW_SCISSOR 0x08
|
||||||
#define LP_SETUP_NEW_VIEWPORTS 0x10
|
#define LP_SETUP_NEW_VIEWPORTS 0x10
|
||||||
|
#define LP_SETUP_NEW_SSBOS 0x20
|
||||||
|
|
||||||
struct lp_setup_variant;
|
struct lp_setup_variant;
|
||||||
|
|
||||||
|
@ -143,6 +143,11 @@ struct lp_setup_context
|
||||||
const void *stored_data;
|
const void *stored_data;
|
||||||
} constants[LP_MAX_TGSI_CONST_BUFFERS];
|
} constants[LP_MAX_TGSI_CONST_BUFFERS];
|
||||||
|
|
||||||
|
/** fragment shader buffers */
|
||||||
|
struct {
|
||||||
|
struct pipe_shader_buffer current;
|
||||||
|
} ssbos[LP_MAX_TGSI_SHADER_BUFFERS];
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct pipe_blend_color current;
|
struct pipe_blend_color current;
|
||||||
uint8_t *stored;
|
uint8_t *stored;
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
#define LP_NEW_GS 0x10000
|
#define LP_NEW_GS 0x10000
|
||||||
#define LP_NEW_SO 0x20000
|
#define LP_NEW_SO 0x20000
|
||||||
#define LP_NEW_SO_BUFFERS 0x40000
|
#define LP_NEW_SO_BUFFERS 0x40000
|
||||||
|
#define LP_NEW_FS_SSBOS 0x80000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -255,6 +255,11 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
|
||||||
ARRAY_SIZE(llvmpipe->constants[PIPE_SHADER_FRAGMENT]),
|
ARRAY_SIZE(llvmpipe->constants[PIPE_SHADER_FRAGMENT]),
|
||||||
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))
|
if (llvmpipe->dirty & (LP_NEW_SAMPLER_VIEW))
|
||||||
lp_setup_set_fragment_sampler_views(llvmpipe->setup,
|
lp_setup_set_fragment_sampler_views(llvmpipe->setup,
|
||||||
llvmpipe->num_sampler_views[PIPE_SHADER_FRAGMENT],
|
llvmpipe->num_sampler_views[PIPE_SHADER_FRAGMENT],
|
||||||
|
|
|
@ -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.
|
* 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.delete_fs_state = llvmpipe_delete_fs_state;
|
||||||
|
|
||||||
llvmpipe->pipe.set_constant_buffer = llvmpipe_set_constant_buffer;
|
llvmpipe->pipe.set_constant_buffer = llvmpipe_set_constant_buffer;
|
||||||
|
|
||||||
|
llvmpipe->pipe.set_shader_buffers = llvmpipe_set_shader_buffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -646,7 +646,8 @@ llvmpipe_is_resource_referenced( struct pipe_context *pipe,
|
||||||
struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
|
struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
|
||||||
if (!(presource->bind & (PIPE_BIND_DEPTH_STENCIL |
|
if (!(presource->bind & (PIPE_BIND_DEPTH_STENCIL |
|
||||||
PIPE_BIND_RENDER_TARGET |
|
PIPE_BIND_RENDER_TARGET |
|
||||||
PIPE_BIND_SAMPLER_VIEW)))
|
PIPE_BIND_SAMPLER_VIEW |
|
||||||
|
PIPE_BIND_SHADER_BUFFER)))
|
||||||
return LP_UNREFERENCED;
|
return LP_UNREFERENCED;
|
||||||
|
|
||||||
return lp_setup_is_resource_referenced(llvmpipe->setup, presource);
|
return lp_setup_is_resource_referenced(llvmpipe->setup, presource);
|
||||||
|
|
Loading…
Reference in New Issue