r300g: postpone fragment shader state validation until draw_vbo
This commit is contained in:
parent
d8361400b7
commit
4af3fe857d
|
@ -447,6 +447,13 @@ enum r300_hiz_func {
|
|||
HIZ_FUNC_MIN,
|
||||
};
|
||||
|
||||
/* For deferred fragment shader state validation. */
|
||||
enum r300_fs_validity_status {
|
||||
FRAGMENT_SHADER_VALID, /* No need to change/validate the FS. */
|
||||
FRAGMENT_SHADER_MAYBE_DIRTY,/* Validate the FS if external state was changed. */
|
||||
FRAGMENT_SHADER_DIRTY /* Always validate the FS (if the FS was changed) */
|
||||
};
|
||||
|
||||
struct r300_context {
|
||||
/* Parent class */
|
||||
struct pipe_context context;
|
||||
|
@ -598,6 +605,10 @@ struct r300_context {
|
|||
enum r300_hiz_func hiz_func;
|
||||
/* HiZ clear value. */
|
||||
uint32_t hiz_clear_value;
|
||||
/* Whether fragment shader needs to be validated. */
|
||||
enum r300_fs_validity_status fs_status;
|
||||
/* Framebuffer multi-write. */
|
||||
boolean fb_multiwrite;
|
||||
|
||||
void *dsa_decompress_zmask;
|
||||
|
||||
|
|
|
@ -387,8 +387,7 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state)
|
|||
if (r300->screen->caps.is_r500) {
|
||||
rb3d_cctl = R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE;
|
||||
}
|
||||
if (fb->nr_cbufs &&
|
||||
r300_fragment_shader_writes_all(r300_fs(r300))) {
|
||||
if (fb->nr_cbufs && r300->fb_multiwrite) {
|
||||
rb3d_cctl |= R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs);
|
||||
}
|
||||
|
||||
|
@ -483,7 +482,7 @@ void r300_emit_fb_state_pipelined(struct r300_context *r300,
|
|||
|
||||
/* If we use the multiwrite feature, the colorbuffers 2,3,4 must be
|
||||
* marked as UNUSED in the US block. */
|
||||
if (r300_fragment_shader_writes_all(r300_fs(r300))) {
|
||||
if (r300->fb_multiwrite) {
|
||||
num_cbufs = MIN2(num_cbufs, 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -969,24 +969,14 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader)
|
|||
{
|
||||
struct r300_context* r300 = r300_context(pipe);
|
||||
struct r300_fragment_shader* fs = (struct r300_fragment_shader*)shader;
|
||||
struct pipe_framebuffer_state *fb = r300->fb_state.state;
|
||||
boolean last_multi_write;
|
||||
|
||||
if (fs == NULL) {
|
||||
r300->fs.state = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
last_multi_write = r300_fragment_shader_writes_all(r300_fs(r300));
|
||||
|
||||
r300->fs.state = fs;
|
||||
r300_pick_fragment_shader(r300);
|
||||
r300_mark_fs_code_dirty(r300);
|
||||
|
||||
if (fb->nr_cbufs > 1 &&
|
||||
last_multi_write != r300_fragment_shader_writes_all(fs)) {
|
||||
r300_mark_fb_state_dirty(r300, R300_CHANGED_MULTIWRITE);
|
||||
}
|
||||
r300->fs_status = FRAGMENT_SHADER_DIRTY;
|
||||
|
||||
r300_mark_atom_dirty(r300, &r300->rs_block_state); /* Will be updated before the emission. */
|
||||
}
|
||||
|
@ -1256,8 +1246,8 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state)
|
|||
}
|
||||
|
||||
if (last_frag_clamp != r300->frag_clamp &&
|
||||
r300->fs.state && r300_pick_fragment_shader(r300)) {
|
||||
r300_mark_fs_code_dirty(r300);
|
||||
r300->fs_status == FRAGMENT_SHADER_VALID) {
|
||||
r300->fs_status = FRAGMENT_SHADER_MAYBE_DIRTY;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1555,7 +1545,8 @@ static void r300_set_viewport_state(struct pipe_context* pipe,
|
|||
}
|
||||
|
||||
r300_mark_atom_dirty(r300, &r300->viewport_state);
|
||||
if (r300->fs.state && r300_fs(r300)->shader->inputs.wpos != ATTR_UNUSED) {
|
||||
if (r300->fs.state && r300_fs(r300)->shader &&
|
||||
r300_fs(r300)->shader->inputs.wpos != ATTR_UNUSED) {
|
||||
r300_mark_atom_dirty(r300, &r300->fs_rc_constant_state);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -961,11 +961,10 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
|
|||
r300->textures_state.size = size;
|
||||
|
||||
/* Pick a fragment shader based on either the texture compare state
|
||||
* or the uses_pitch flag. */
|
||||
if (r300->fs.state && count) {
|
||||
if (r300_pick_fragment_shader(r300)) {
|
||||
r300_mark_fs_code_dirty(r300);
|
||||
}
|
||||
* or the uses_pitch flag or some other external state. */
|
||||
if (count &&
|
||||
r300->fs_status == FRAGMENT_SHADER_VALID) {
|
||||
r300->fs_status = FRAGMENT_SHADER_MAYBE_DIRTY;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -994,6 +993,34 @@ static void r300_decompress_depth_textures(struct r300_context *r300)
|
|||
}
|
||||
}
|
||||
|
||||
static void r300_validate_fragment_shader(struct r300_context *r300)
|
||||
{
|
||||
struct pipe_framebuffer_state *fb = r300->fb_state.state;
|
||||
|
||||
if (r300->fs.state && r300->fs_status != FRAGMENT_SHADER_VALID) {
|
||||
/* Pick the fragment shader based on external states.
|
||||
* Then mark the state dirty if the fragment shader is either dirty
|
||||
* or the function r300_pick_fragment_shader changed the shader. */
|
||||
if (r300_pick_fragment_shader(r300) ||
|
||||
r300->fs_status == FRAGMENT_SHADER_DIRTY) {
|
||||
/* Mark the state atom as dirty. */
|
||||
r300_mark_fs_code_dirty(r300);
|
||||
|
||||
/* Does Multiwrite need to be changed? */
|
||||
if (fb->nr_cbufs > 1) {
|
||||
boolean new_multiwrite =
|
||||
r300_fragment_shader_writes_all(r300_fs(r300));
|
||||
|
||||
if (r300->fb_multiwrite != new_multiwrite) {
|
||||
r300->fb_multiwrite = new_multiwrite;
|
||||
r300_mark_fb_state_dirty(r300, R300_CHANGED_MULTIWRITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
r300->fs_status = FRAGMENT_SHADER_VALID;
|
||||
}
|
||||
}
|
||||
|
||||
void r300_update_derived_state(struct r300_context* r300)
|
||||
{
|
||||
if (r300->textures_state.dirty) {
|
||||
|
@ -1001,6 +1028,8 @@ void r300_update_derived_state(struct r300_context* r300)
|
|||
r300_merge_textures_and_samplers(r300);
|
||||
}
|
||||
|
||||
r300_validate_fragment_shader(r300);
|
||||
|
||||
if (r300->rs_block_state.dirty) {
|
||||
r300_update_rs_block(r300);
|
||||
|
||||
|
|
Loading…
Reference in New Issue