Commit c8fe3b9d authored by Marek Olšák's avatar Marek Olšák

st/mesa: completely rewrite state atoms

The goal is to do this in st_validate_state:
   while (dirty)
      atoms[u_bit_scan(&dirty)]->update(st);

That implies that atoms can't specify which flags they consume.
There is exactly one ST_NEW_* flag for each atom. (58 flags in total)

There are macros that combine multiple flags into one for easier use.

All _NEW_* flags are translated into ST_NEW_* flags in st_invalidate_state.
st/mesa doesn't keep the _NEW_* flags after that.

torcs is 2% faster between the previous patch and the end of this series.

v2: - add st_atom_list.h to Makefile.sources
Reviewed-by: default avatarNicolai Hähnle <nicolai.haehnle@amd.com>
parent 53bc2892
......@@ -409,6 +409,7 @@ STATETRACKER_FILES = \
state_tracker/st_atom_depth.c \
state_tracker/st_atom_framebuffer.c \
state_tracker/st_atom.h \
state_tracker/st_atom_list.h \
state_tracker/st_atom_image.c \
state_tracker/st_atom_msaa.c \
state_tracker/st_atom_pixeltransfer.c \
......
......@@ -37,87 +37,18 @@
#include "st_manager.h"
/**
* This is used to initialize st->render_atoms[].
*/
static const struct st_tracked_state *render_atoms[] =
{
&st_update_depth_stencil_alpha,
&st_update_clip,
&st_update_fp,
&st_update_gp,
&st_update_tep,
&st_update_tcp,
&st_update_vp,
&st_update_rasterizer,
&st_update_polygon_stipple,
&st_update_viewport,
&st_update_scissor,
&st_update_window_rectangles,
&st_update_blend,
&st_update_vertex_texture,
&st_update_fragment_texture,
&st_update_geometry_texture,
&st_update_tessctrl_texture,
&st_update_tesseval_texture,
&st_update_sampler, /* depends on update_*_texture for swizzle */
&st_bind_vs_images,
&st_bind_tcs_images,
&st_bind_tes_images,
&st_bind_gs_images,
&st_bind_fs_images,
&st_update_framebuffer, /* depends on update_*_texture and bind_*_images */
&st_update_msaa,
&st_update_sample_shading,
&st_update_vs_constants,
&st_update_tcs_constants,
&st_update_tes_constants,
&st_update_gs_constants,
&st_update_fs_constants,
&st_bind_vs_ubos,
&st_bind_tcs_ubos,
&st_bind_tes_ubos,
&st_bind_fs_ubos,
&st_bind_gs_ubos,
&st_bind_vs_atomics,
&st_bind_tcs_atomics,
&st_bind_tes_atomics,
&st_bind_fs_atomics,
&st_bind_gs_atomics,
&st_bind_vs_ssbos,
&st_bind_tcs_ssbos,
&st_bind_tes_ssbos,
&st_bind_fs_ssbos,
&st_bind_gs_ssbos,
&st_update_pixel_transfer,
&st_update_tess,
/* this must be done after the vertex program update */
&st_update_array
};
/**
* This is used to initialize st->compute_atoms[].
*/
static const struct st_tracked_state *compute_atoms[] =
/* The list state update functions. */
static const struct st_tracked_state *atoms[] =
{
&st_update_cp,
&st_update_compute_texture,
&st_update_sampler, /* depends on update_compute_texture for swizzle */
&st_update_cs_constants,
&st_bind_cs_ubos,
&st_bind_cs_atomics,
&st_bind_cs_ssbos,
&st_bind_cs_images,
#define ST_STATE(FLAG, st_update) &st_update,
#include "st_atom_list.h"
#undef ST_STATE
};
void st_init_atoms( struct st_context *st )
{
/* no-op */
STATIC_ASSERT(ARRAY_SIZE(atoms) <= 64);
}
......@@ -127,13 +58,6 @@ void st_destroy_atoms( struct st_context *st )
}
static bool
check_state(const struct st_state_flags *a, const struct st_state_flags *b)
{
return (a->mesa & b->mesa) || (a->st & b->st);
}
/* Too complex to figure out, just check every time:
*/
static void check_program_state( struct st_context *st )
......@@ -141,13 +65,13 @@ static void check_program_state( struct st_context *st )
struct gl_context *ctx = st->ctx;
if (ctx->VertexProgram._Current != &st->vp->Base)
st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
st->dirty |= ST_NEW_VERTEX_PROGRAM;
if (ctx->FragmentProgram._Current != &st->fp->Base)
st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
st->dirty |= ST_NEW_FRAGMENT_PROGRAM;
if (ctx->GeometryProgram._Current != &st->gp->Base)
st->dirty.st |= ST_NEW_GEOMETRY_PROGRAM;
st->dirty |= ST_NEW_GEOMETRY_PROGRAM;
}
static void check_attrib_edgeflag(struct st_context *st)
......@@ -165,14 +89,14 @@ static void check_attrib_edgeflag(struct st_context *st)
arrays[VERT_ATTRIB_EDGEFLAG]->StrideB != 0;
if (vertdata_edgeflags != st->vertdata_edgeflags) {
st->vertdata_edgeflags = vertdata_edgeflags;
st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
st->dirty |= ST_NEW_VERTEX_PROGRAM;
}
edgeflag_culls_prims = edgeflags_enabled && !vertdata_edgeflags &&
!st->ctx->Current.Attrib[VERT_ATTRIB_EDGEFLAG][0];
if (edgeflag_culls_prims != st->edgeflag_culls_prims) {
st->edgeflag_culls_prims = edgeflag_culls_prims;
st->dirty.st |= ST_NEW_RASTERIZER;
st->dirty |= ST_NEW_RASTERIZER;
}
}
......@@ -183,49 +107,45 @@ static void check_attrib_edgeflag(struct st_context *st)
void st_validate_state( struct st_context *st, enum st_pipeline pipeline )
{
const struct st_tracked_state **atoms;
struct st_state_flags *state;
GLuint num_atoms;
GLuint i;
uint64_t dirty, pipeline_mask;
uint32_t dirty_lo, dirty_hi;
/* Get Mesa driver state. */
st->dirty |= st->ctx->NewDriverState & ST_ALL_STATES_MASK;
st->ctx->NewDriverState = 0;
/* Get pipeline state. */
switch (pipeline) {
case ST_PIPELINE_RENDER:
atoms = render_atoms;
num_atoms = ARRAY_SIZE(render_atoms);
state = &st->dirty;
case ST_PIPELINE_RENDER:
check_attrib_edgeflag(st);
check_program_state(st);
st_manager_validate_framebuffers(st);
pipeline_mask = ST_PIPELINE_RENDER_STATE_MASK;
break;
case ST_PIPELINE_COMPUTE:
atoms = compute_atoms;
num_atoms = ARRAY_SIZE(compute_atoms);
state = &st->dirty_cp;
pipeline_mask = ST_PIPELINE_COMPUTE_STATE_MASK;
break;
default:
unreachable("Invalid pipeline specified");
}
/* Get Mesa driver state. */
st->dirty.st |= st->ctx->NewDriverState;
st->dirty_cp.st |= st->ctx->NewDriverState;
st->ctx->NewDriverState = 0;
if (pipeline == ST_PIPELINE_RENDER) {
check_attrib_edgeflag(st);
check_program_state(st);
st_manager_validate_framebuffers(st);
}
if (state->st == 0 && state->mesa == 0)
dirty = st->dirty & pipeline_mask;
if (!dirty)
return;
/*printf("%s %x/%x\n", __func__, state->mesa, state->st);*/
dirty_lo = dirty;
dirty_hi = dirty >> 32;
for (i = 0; i < num_atoms; i++) {
if (check_state(state, &atoms[i]->dirty))
atoms[i]->update( st );
}
/* Update states.
*
* Don't use u_bit_scan64, it may be slower on 32-bit.
*/
while (dirty_lo)
atoms[u_bit_scan(&dirty_lo)]->update(st);
while (dirty_hi)
atoms[32 + u_bit_scan(&dirty_hi)]->update(st);
memset(state, 0, sizeof(*state));
/* Clear the render or compute state bits. */
st->dirty &= ~pipeline_mask;
}
This diff is collapsed.
......@@ -690,9 +690,5 @@ static void update_array(struct st_context *st)
const struct st_tracked_state st_update_array = {
{ /* dirty */
_NEW_CURRENT_ATTRIB, /* mesa */
ST_NEW_VERTEX_ARRAYS | ST_NEW_VERTEX_PROGRAM, /* st */
},
update_array /* update */
};
......@@ -79,10 +79,6 @@ bind_vs_atomics(struct st_context *st)
}
const struct st_tracked_state st_bind_vs_atomics = {
{
0,
ST_NEW_VERTEX_PROGRAM | ST_NEW_ATOMIC_BUFFER,
},
bind_vs_atomics
};
......@@ -96,10 +92,6 @@ bind_fs_atomics(struct st_context *st)
}
const struct st_tracked_state st_bind_fs_atomics = {
{
0,
ST_NEW_FRAGMENT_PROGRAM | ST_NEW_ATOMIC_BUFFER,
},
bind_fs_atomics
};
......@@ -113,10 +105,6 @@ bind_gs_atomics(struct st_context *st)
}
const struct st_tracked_state st_bind_gs_atomics = {
{
0,
ST_NEW_GEOMETRY_PROGRAM | ST_NEW_ATOMIC_BUFFER,
},
bind_gs_atomics
};
......@@ -130,10 +118,6 @@ bind_tcs_atomics(struct st_context *st)
}
const struct st_tracked_state st_bind_tcs_atomics = {
{
0,
ST_NEW_TESSCTRL_PROGRAM | ST_NEW_ATOMIC_BUFFER,
},
bind_tcs_atomics
};
......@@ -147,10 +131,6 @@ bind_tes_atomics(struct st_context *st)
}
const struct st_tracked_state st_bind_tes_atomics = {
{
0,
ST_NEW_TESSEVAL_PROGRAM | ST_NEW_ATOMIC_BUFFER,
},
bind_tes_atomics
};
......@@ -164,9 +144,5 @@ bind_cs_atomics(struct st_context *st)
}
const struct st_tracked_state st_bind_cs_atomics = {
{
0,
ST_NEW_COMPUTE_PROGRAM | ST_NEW_ATOMIC_BUFFER,
},
bind_cs_atomics
};
......@@ -283,9 +283,5 @@ update_blend( struct st_context *st )
const struct st_tracked_state st_update_blend = {
{ /* dirty */
(_NEW_COLOR | _NEW_MULTISAMPLE), /* XXX _NEW_BLEND someday? */ /* mesa */
0, /* st */
},
update_blend, /* update */
};
......@@ -71,9 +71,5 @@ static void update_clip( struct st_context *st )
const struct st_tracked_state st_update_clip = {
{ /* dirty */
_NEW_TRANSFORM | _NEW_PROJECTION, /* mesa */
ST_NEW_VERTEX_PROGRAM, /* st */
},
update_clip /* update */
};
......@@ -145,10 +145,6 @@ static void update_vs_constants(struct st_context *st )
const struct st_tracked_state st_update_vs_constants = {
{ /* dirty */
_NEW_PROGRAM_CONSTANTS, /* mesa */
ST_NEW_VERTEX_PROGRAM, /* st */
},
update_vs_constants /* update */
};
......@@ -167,10 +163,6 @@ static void update_fs_constants(struct st_context *st )
const struct st_tracked_state st_update_fs_constants = {
{ /* dirty */
_NEW_PROGRAM_CONSTANTS, /* mesa */
ST_NEW_FRAGMENT_PROGRAM, /* st */
},
update_fs_constants /* update */
};
......@@ -188,10 +180,6 @@ static void update_gs_constants(struct st_context *st )
}
const struct st_tracked_state st_update_gs_constants = {
{ /* dirty */
_NEW_PROGRAM_CONSTANTS, /* mesa */
ST_NEW_GEOMETRY_PROGRAM, /* st */
},
update_gs_constants /* update */
};
......@@ -209,10 +197,6 @@ static void update_tcs_constants(struct st_context *st )
}
const struct st_tracked_state st_update_tcs_constants = {
{ /* dirty */
_NEW_PROGRAM_CONSTANTS, /* mesa */
ST_NEW_TESSCTRL_PROGRAM, /* st */
},
update_tcs_constants /* update */
};
......@@ -230,10 +214,6 @@ static void update_tes_constants(struct st_context *st )
}
const struct st_tracked_state st_update_tes_constants = {
{ /* dirty */
_NEW_PROGRAM_CONSTANTS, /* mesa */
ST_NEW_TESSEVAL_PROGRAM, /* st */
},
update_tes_constants /* update */
};
......@@ -251,10 +231,6 @@ static void update_cs_constants(struct st_context *st )
}
const struct st_tracked_state st_update_cs_constants = {
{ /* dirty */
_NEW_PROGRAM_CONSTANTS, /* mesa */
ST_NEW_COMPUTE_PROGRAM, /* st */
},
update_cs_constants /* update */
};
......@@ -308,10 +284,6 @@ static void bind_vs_ubos(struct st_context *st)
}
const struct st_tracked_state st_bind_vs_ubos = {
{
0,
ST_NEW_VERTEX_PROGRAM | ST_NEW_UNIFORM_BUFFER,
},
bind_vs_ubos
};
......@@ -327,10 +299,6 @@ static void bind_fs_ubos(struct st_context *st)
}
const struct st_tracked_state st_bind_fs_ubos = {
{
0,
ST_NEW_FRAGMENT_PROGRAM | ST_NEW_UNIFORM_BUFFER,
},
bind_fs_ubos
};
......@@ -346,10 +314,6 @@ static void bind_gs_ubos(struct st_context *st)
}
const struct st_tracked_state st_bind_gs_ubos = {
{
0,
ST_NEW_GEOMETRY_PROGRAM | ST_NEW_UNIFORM_BUFFER,
},
bind_gs_ubos
};
......@@ -365,10 +329,6 @@ static void bind_tcs_ubos(struct st_context *st)
}
const struct st_tracked_state st_bind_tcs_ubos = {
{
0,
ST_NEW_TESSCTRL_PROGRAM | ST_NEW_UNIFORM_BUFFER,
},
bind_tcs_ubos
};
......@@ -384,10 +344,6 @@ static void bind_tes_ubos(struct st_context *st)
}
const struct st_tracked_state st_bind_tes_ubos = {
{
0,
ST_NEW_TESSEVAL_PROGRAM | ST_NEW_UNIFORM_BUFFER,
},
bind_tes_ubos
};
......@@ -404,9 +360,5 @@ static void bind_cs_ubos(struct st_context *st)
}
const struct st_tracked_state st_bind_cs_ubos = {
{
0,
ST_NEW_COMPUTE_PROGRAM | ST_NEW_UNIFORM_BUFFER,
},
bind_cs_ubos
};
......@@ -161,9 +161,5 @@ update_depth_stencil_alpha(struct st_context *st)
const struct st_tracked_state st_update_depth_stencil_alpha = {
{ /* dirty */
(_NEW_DEPTH|_NEW_STENCIL|_NEW_COLOR|_NEW_BUFFERS),/* mesa */
0, /* st */
},
update_depth_stencil_alpha /* update */
};
......@@ -215,10 +215,6 @@ update_framebuffer_state( struct st_context *st )
const struct st_tracked_state st_update_framebuffer = {
{ /* dirty */
_NEW_BUFFERS, /* mesa */
ST_NEW_FRAMEBUFFER, /* st */
},
update_framebuffer_state /* update */
};
......@@ -146,10 +146,6 @@ static void bind_vs_images(struct st_context *st)
}
const struct st_tracked_state st_bind_vs_images = {
{
_NEW_TEXTURE,
ST_NEW_VERTEX_PROGRAM | ST_NEW_IMAGE_UNITS,
},
bind_vs_images
};
......@@ -165,10 +161,6 @@ static void bind_fs_images(struct st_context *st)
}
const struct st_tracked_state st_bind_fs_images = {
{
_NEW_TEXTURE,
ST_NEW_FRAGMENT_PROGRAM | ST_NEW_IMAGE_UNITS,
},
bind_fs_images
};
......@@ -184,10 +176,6 @@ static void bind_gs_images(struct st_context *st)
}
const struct st_tracked_state st_bind_gs_images = {
{
_NEW_TEXTURE,
ST_NEW_GEOMETRY_PROGRAM | ST_NEW_IMAGE_UNITS,
},
bind_gs_images
};
......@@ -203,10 +191,6 @@ static void bind_tcs_images(struct st_context *st)
}
const struct st_tracked_state st_bind_tcs_images = {
{
_NEW_TEXTURE,
ST_NEW_TESSCTRL_PROGRAM | ST_NEW_IMAGE_UNITS,
},
bind_tcs_images
};
......@@ -222,10 +206,6 @@ static void bind_tes_images(struct st_context *st)
}
const struct st_tracked_state st_bind_tes_images = {
{
_NEW_TEXTURE,
ST_NEW_TESSEVAL_PROGRAM | ST_NEW_IMAGE_UNITS,
},
bind_tes_images
};
......@@ -241,9 +221,5 @@ static void bind_cs_images(struct st_context *st)
}
const struct st_tracked_state st_bind_cs_images = {
{
_NEW_TEXTURE,
ST_NEW_COMPUTE_PROGRAM | ST_NEW_IMAGE_UNITS,
},
bind_cs_images
};
/* Render (non-compute) states must be first. */
ST_STATE(ST_NEW_DSA, st_update_depth_stencil_alpha)
ST_STATE(ST_NEW_CLIP_STATE, st_update_clip)
ST_STATE(ST_NEW_FS_STATE, st_update_fp)
ST_STATE(ST_NEW_GS_STATE, st_update_gp)
ST_STATE(ST_NEW_TES_STATE, st_update_tep)
ST_STATE(ST_NEW_TCS_STATE, st_update_tcp)
ST_STATE(ST_NEW_VS_STATE, st_update_vp)
ST_STATE(ST_NEW_RASTERIZER, st_update_rasterizer)
ST_STATE(ST_NEW_POLY_STIPPLE, st_update_polygon_stipple)
ST_STATE(ST_NEW_VIEWPORT, st_update_viewport)
ST_STATE(ST_NEW_SCISSOR, st_update_scissor)
ST_STATE(ST_NEW_WINDOW_RECTANGLES, st_update_window_rectangles)
ST_STATE(ST_NEW_BLEND, st_update_blend)
ST_STATE(ST_NEW_VS_SAMPLER_VIEWS, st_update_vertex_texture)
ST_STATE(ST_NEW_FS_SAMPLER_VIEWS, st_update_fragment_texture)
ST_STATE(ST_NEW_GS_SAMPLER_VIEWS, st_update_geometry_texture)
ST_STATE(ST_NEW_TCS_SAMPLER_VIEWS, st_update_tessctrl_texture)
ST_STATE(ST_NEW_TES_SAMPLER_VIEWS, st_update_tesseval_texture)
/* Non-compute samplers. */
ST_STATE(ST_NEW_RENDER_SAMPLERS, st_update_sampler) /* depends on update_*_texture for swizzle */
ST_STATE(ST_NEW_VS_IMAGES, st_bind_vs_images)
ST_STATE(ST_NEW_TCS_IMAGES, st_bind_tcs_images)
ST_STATE(ST_NEW_TES_IMAGES, st_bind_tes_images)
ST_STATE(ST_NEW_GS_IMAGES, st_bind_gs_images)
ST_STATE(ST_NEW_FS_IMAGES, st_bind_fs_images)
ST_STATE(ST_NEW_FB_STATE, st_update_framebuffer) /* depends on update_*_texture and bind_*_images */
ST_STATE(ST_NEW_SAMPLE_MASK, st_update_msaa)
ST_STATE(ST_NEW_SAMPLE_SHADING, st_update_sample_shading)
ST_STATE(ST_NEW_VS_CONSTANTS, st_update_vs_constants)
ST_STATE(ST_NEW_TCS_CONSTANTS, st_update_tcs_constants)
ST_STATE(ST_NEW_TES_CONSTANTS, st_update_tes_constants)
ST_STATE(ST_NEW_GS_CONSTANTS, st_update_gs_constants)
ST_STATE(ST_NEW_FS_CONSTANTS, st_update_fs_constants)
ST_STATE(ST_NEW_VS_UBOS, st_bind_vs_ubos)
ST_STATE(ST_NEW_TCS_UBOS, st_bind_tcs_ubos)
ST_STATE(ST_NEW_TES_UBOS, st_bind_tes_ubos)
ST_STATE(ST_NEW_FS_UBOS, st_bind_fs_ubos)
ST_STATE(ST_NEW_GS_UBOS, st_bind_gs_ubos)
ST_STATE(ST_NEW_VS_ATOMICS, st_bind_vs_atomics)
ST_STATE(ST_NEW_TCS_ATOMICS, st_bind_tcs_atomics)
ST_STATE(ST_NEW_TES_ATOMICS, st_bind_tes_atomics)
ST_STATE(ST_NEW_FS_ATOMICS, st_bind_fs_atomics)
ST_STATE(ST_NEW_GS_ATOMICS, st_bind_gs_atomics)
ST_STATE(ST_NEW_VS_SSBOS, st_bind_vs_ssbos)
ST_STATE(ST_NEW_TCS_SSBOS, st_bind_tcs_ssbos)
ST_STATE(ST_NEW_TES_SSBOS, st_bind_tes_ssbos)
ST_STATE(ST_NEW_FS_SSBOS, st_bind_fs_ssbos)
ST_STATE(ST_NEW_GS_SSBOS, st_bind_gs_ssbos)
ST_STATE(ST_NEW_PIXEL_TRANSFER, st_update_pixel_transfer)
ST_STATE(ST_NEW_TESS_STATE, st_update_tess)
/* this must be done after the vertex program update */
ST_STATE(ST_NEW_VERTEX_ARRAYS, st_update_array)
/* Compute states must be last. */
ST_STATE(ST_NEW_CS_STATE, st_update_cp)
ST_STATE(ST_NEW_CS_SAMPLER_VIEWS, st_update_compute_texture)
ST_STATE(ST_NEW_CS_SAMPLERS, st_update_sampler) /* depends on update_compute_texture for swizzle */
ST_STATE(ST_NEW_CS_CONSTANTS, st_update_cs_constants)
ST_STATE(ST_NEW_CS_UBOS, st_bind_cs_ubos)
ST_STATE(ST_NEW_CS_ATOMICS, st_bind_cs_atomics)
ST_STATE(ST_NEW_CS_SSBOS, st_bind_cs_ssbos)
ST_STATE(ST_NEW_CS_IMAGES, st_bind_cs_images)
......@@ -86,17 +86,9 @@ static void update_sample_shading( struct st_context *st )
}
const struct st_tracked_state st_update_msaa = {
{ /* dirty */
(_NEW_MULTISAMPLE | _NEW_BUFFERS), /* mesa */
ST_NEW_FRAMEBUFFER, /* st */
},
update_sample_mask /* update */
};
const struct st_tracked_state st_update_sample_shading = {
{ /* dirty */
(_NEW_MULTISAMPLE | _NEW_PROGRAM | _NEW_BUFFERS), /* mesa */
ST_NEW_FRAGMENT_PROGRAM | ST_NEW_FRAMEBUFFER, /* st */
},
update_sample_shading /* update */
};
......@@ -102,9 +102,5 @@ update_pixel_transfer(struct st_context *st)
const struct st_tracked_state st_update_pixel_transfer = {
{ /* dirty */
_NEW_PIXEL, /* mesa */
0, /* st */
},
update_pixel_transfer /* update */
};
......@@ -290,21 +290,5 @@ static void update_raster_state( struct st_context *st )
}
const struct st_tracked_state st_update_rasterizer = {
{
(_NEW_BUFFERS |
_NEW_LIGHT |