summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2013-09-09 12:38:27 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2013-09-09 13:51:19 +0200
commit7d5eafe76d06e6611a6e1e8c175f11a95a4f371f (patch)
tree8f5ef01813ada37354040d37227adebf27c72ade
parent199c781c703eb3b4986bd454d29a5049f19290ff (diff)
driver: fix cousins of MSAA hang bug
- Change the order in `reset_context` as well - Clobber PS INPUTS state when MSAA samples changed to make sure it's always written, as we don't know the current value anymore.
-rw-r--r--doc/kernel_bugs.md22
-rw-r--r--native/driver/etna_pipe.c21
2 files changed, 42 insertions, 1 deletions
diff --git a/doc/kernel_bugs.md b/doc/kernel_bugs.md
index 0ccb33a..76e5445 100644
--- a/doc/kernel_bugs.md
+++ b/doc/kernel_bugs.md
@@ -31,3 +31,25 @@ signal causes the kernel to run out of signals. This causes hangs in rendering.
Status: workaround found (see `ETNA_MAX_UNSIGNALED_FLUSHES`)
+Command buffer memory management on cubox
+-------------------------------------------
+
+ <_rmk_> err, this is not good.
+ <_rmk_> gckCOMMAND_Start: command queue is at 0xe7846000
+ <_rmk_> gckCOMMAND_Start: WL 380000c8 0cf6d19f 40000002 10281000
+ <_rmk_> that's what the first 4 words should've been at the beginning (and where when the GPU was started)
+ <_rmk_> they then conveniently become: 4000002C 19CE0000 AAAAAAAA AAAAAAAA
+ <_rmk_> the first two change because of the wait being converted to a link
+ <_rmk_> the second two...
+ <_rmk_> well, 0xaaaaaaaa is the free page poisoning.
+ <_rmk_> which suggests that the GPU command page was freed while still in use
+ <_rmk_> ah ha, that'll be how. get lucky with the cache behaviour and this is what happens...
+ <_rmk_> page poisoning enabled. When a lowmem page is allocated, it's memset() through its lowmem mapping, which is cacheable.
+ <_rmk_> this data can sit in the CPU cache.
+ <_rmk_> it is then ioremap()'d (which I've been dead against for years) which creates a *device* mapping.
+ <_rmk_> we then write the wait/link through the device mapping.
+ <_rmk_> at some point later, the cache lines get evicted from the _normal memory_ mapping.
+ <_rmk_> thereby overwriting the original wait/link commands in the GPU stream with 0xAAAAAAAA
+ <_rmk_> I wonder what that a command word with a bit pattern of 10101 in the top 5 bits tells the GPU to do...
+ <_rmk_> the only thing I can say is... if people would damn well listen to me when I say "don't do this" then you wouldn't get these bugs.
+ <_rmk_> this is one of the reasons why my check in ioremap.c exists to prevent system memory being ioremap'd and therefore this kind of issue cropping up
diff --git a/native/driver/etna_pipe.c b/native/driver/etna_pipe.c
index 24c6eb7..4670355 100644
--- a/native/driver/etna_pipe.c
+++ b/native/driver/etna_pipe.c
@@ -105,6 +105,11 @@ static void reset_context(struct pipe_context *restrict pipe)
uint32_t last_reg, last_fixp, span_start;
ETNA_COALESCE_STATE_OPEN(ETNA_3D_CONTEXT_SIZE);
+ /* multi sample config is set first, and outside of the normal sorting
+ * order, as changing the multisample state clobbers PS.INPUT_COUNT (and
+ * possibly PS.TEMP_REGISTER_CONTROL).
+ */
+ /*03818*/ EMIT_STATE(GL_MULTI_SAMPLE_CONFIG, GL_MULTI_SAMPLE_CONFIG);
/* below code generated by gen_weave_state.py, keep this in sync with sync_context! */
/* begin only EMIT_STATE -- make sure no new etna_reserve calls are done here directly
* or indirectly */
@@ -249,7 +254,6 @@ static void reset_context(struct pipe_context *restrict pipe)
}
}
/*03814*/ EMIT_STATE(GL_VERTEX_ELEMENT_CONFIG, GL_VERTEX_ELEMENT_CONFIG);
- /*03818*/ EMIT_STATE(GL_MULTI_SAMPLE_CONFIG, GL_MULTI_SAMPLE_CONFIG);
/*0381C*/ EMIT_STATE(GL_VARYING_TOTAL_COMPONENTS, GL_VARYING_TOTAL_COMPONENTS);
/*03820*/ EMIT_STATE(GL_VARYING_NUM_COMPONENTS, GL_VARYING_NUM_COMPONENTS);
for(int x=0; x<2; ++x)
@@ -316,6 +320,21 @@ static void sync_context(struct pipe_context *restrict pipe)
e->gpu3d.num_vertex_elements = e->vertex_elements->num_elements;
+ /* If MULTI_SAMPLE_CONFIG.MSAA_SAMPLES changed, clobber affected shader
+ * state to make sure it is always rewritten. */
+ if(dirty & (ETNA_STATE_FRAMEBUFFER))
+ {
+ if((e->gpu3d.GL_MULTI_SAMPLE_CONFIG & VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES__MASK) !=
+ (e->framebuffer.GL_MULTI_SAMPLE_CONFIG & VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES__MASK))
+ {
+ /* XXX what does the GPU set these states to on MSAA samples change? Does it do the right thing?
+ * (increase/decrease as necessary) or something else? Just set some invalid value until we know for
+ * sure. */
+ e->gpu3d.PS_INPUT_COUNT = 0xffffffff;
+ e->gpu3d.PS_TEMP_REGISTER_CONTROL = 0xffffffff;
+ }
+ }
+
/*
* Cached state update emission.
* The etna_3d_state structure e->gpu3d is used to keep the current context.