<html>
<head>
<base href="https://bugs.freedesktop.org/">
</head>
<body>
<p>
<div>
<b><a class="bz_bug_link
bz_status_NEW "
title="NEW - HyperZ is broken for r300 (bad z for some micro and macrotiles?)"
href="https://bugs.freedesktop.org/show_bug.cgi?id=110897#c26">Comment # 26</a>
on <a class="bz_bug_link
bz_status_NEW "
title="NEW - HyperZ is broken for r300 (bad z for some micro and macrotiles?)"
href="https://bugs.freedesktop.org/show_bug.cgi?id=110897">bug 110897</a>
from <span class="vcard"><a class="email" href="mailto:u9vata@gmail.com" title="Richard Thier <u9vata@gmail.com>"> <span class="fn">Richard Thier</span></a>
</span></b>
<pre>Okay it is still bad now despite I have compiled with "-O0" flags actually...
To be honest I have no idea actually why it started working last time.
Also now that I step with the debugger I see that a lot of code paths
that I imagine should be taken are never ever taken.
Also when going randomly in the code with gdb I have found the following
things. I just want to document my findings so far with gdb breakpoints in the
driver. These are maybe not general for everyone, but this is what happens on
my very machine and card when debugging r300 code with gdb...
WHAT HAPPENS IN r300_blit.c
===========================
You can roughly follow this stuff here:
<a href="https://github.com/anholt/mesa/blob/master/src/gallium/drivers/r300/r300_blit.c">https://github.com/anholt/mesa/blob/master/src/gallium/drivers/r300/r300_blit.c</a>
0.) Setting of zmask_clear=1 and hiz_clear=0 always happen
----------------------------------------------------------
262 /* Use fast Z clear.
263 * The zbuffer must be in micro-tiled mode, otherwise it locks up. */
264 if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
265 boolean zmask_clear, hiz_clear;
266
267 /* If both depth and stencil are present, they must be cleared
together. */
268 if (fb->zsbuf->texture->format == PIPE_FORMAT_S8_UINT_Z24_UNORM
&&
269 (buffers & PIPE_CLEAR_DEPTHSTENCIL) !=
PIPE_CLEAR_DEPTHSTENCIL) {
270 zmask_clear = FALSE;
271 hiz_clear = FALSE;
272 } else { /* ALWAYS HAPPENS: */
273 zmask_clear = r300_fast_zclear_allowed(r300, buffers);
274 hiz_clear = r300_hiz_clear_allowed(r300);
275 /* FIXME: only for testing! */
276 /*zmask_clear = FALSE;*/
277 /*zmask_clear = TRUE; // - this alone looks bad, bothfalse
look good, zmaks_clear only false hiz_clear untouched is good */
278 /*hiz_clear = FALSE;*/
279 /*hiz_clear = TRUE; // enabling this and falsing zmask_clear
shows picture but FPS is lower in glxgears...*/
We always go where I marked it with "/* ALWAYS HAPPENS */".
r300_fast_zclear_allowed(r300, buffers) return 1
r300_hiz_clear_allowed(r300) returns 0
So:
zmask_clear == 1
hiz_clear == 0
ALWAYS. As I understand the hiz_clear is the thing that clears the
"hierarchical Z" buffer and I suspect this should be returning true instead.
The other for zmask clearn is the one that clears the compessed z-buffer. I had
a bit of a hard time to figure out what these mean, but using the r5xx docs
(despite this card is r300) helped a lot. So zmask is a lossless compressed
z-buffer ram and hiz ram seem to be on the higher hiearchy level.
I have checked what is the body of the latter:
return
300_resource(fb->zsbuf->texture)->tex.hiz_dwords[fb->zsbuf->u.tex.level] != 0;
^^and this body never returns true for some reason. I think this should be
nonzero when HyperZ is properly going on isn't it? I am just running glxgears
and nothing fancy.
1.) "Enabling" HyperZ seem to happen properly
---------------------------------------------
282 /* If we need Hyper-Z. */
283 if (zmask_clear || hiz_clear) {
284 /* Try to obtain the access to Hyper-Z buffers if we don't
have one. */
285 if (!r300->hyperz_enabled &&
286 (r300->screen->caps.is_r500 ||
debug_get_option_hyperz())) {
287 r300->hyperz_enabled =
288 r300->rws->cs_request_feature(r300->cs,
289
RADEON_FID_R300_HYPERZ_ACCESS,
290 TRUE);
291 if (r300->hyperz_enabled) {
292 /* Need to emit HyperZ buffer regs for the first time.
*/
293 r300_mark_fb_state_dirty(r300,
R300_CHANGED_HYPERZ_FLAG);
294 }
295 }
On the first run we get into the cs_request_feature stuff and then the
r300_mark_fb_state_dirty function properly. hiz_clear is never true here, but
the zmask_clear boolean is - see above. The debug_get_option_hyperz() is the
cause why this happens as that is the one that checks the environment variable.
297 /* Setup Hyper-Z clears. */
298 if (r300->hyperz_enabled) {
299 if (zmask_clear) {
300 hyperz_dcv = hyperz->zb_depthclearvalue =
301 r300_depth_clear_value(fb->zsbuf->format, depth,
stencil);
302
303 r300_mark_atom_dirty(r300, &r300->zmask_clear);
304 r300_mark_atom_dirty(r300, &r300->gpu_flush);
305 buffers &= ~PIPE_CLEAR_DEPTHSTENCIL;
306 }
307
308 if (hiz_clear) {
309 r300->hiz_clear_value = r300_hiz_clear_value(depth);
310 r300_mark_atom_dirty(r300, &r300->hiz_clear);
311 r300_mark_atom_dirty(r300, &r300->gpu_flush);
312 }
313 r300->num_z_clears++;
314 }
The zmask_clear part here also runs in every frame. I do not really know what
it means if the r300->zmask_clear atom is dirty. I might need to check if this
actually really means that the clear commands will be sent out to the command
stream of somewhere or not. The depth clear value was FF..FF00 so a lot of Fs
and two zeroes in the end. Sorry it is not in front of me while writing this so
I do not remember the number of Fs just that the upper bits are all ones and
the lowest byte was not.
2.) The CMASK path in the r300_clear(..) never seem to happen
-------------------------------------------------------------
/* src/gallium/drivers/r300/r300_blit.c */
318 /* Use fast color clear for an AA colorbuffer.
319 * The CMASK is shared between all colorbuffers, so we use it
320 * if there is only one colorbuffer bound. */
321 if ((buffers & PIPE_CLEAR_COLOR) && fb->nr_cbufs == 1 &&
fb->cbufs[0]&&
322 r300_resource(fb->cbufs[0]->texture)->tex.cmask_dwords) { ...
Is always false even if I run glxgears with "-samples 4" and adding
RADEUN_DEBUG=msaa showing that inded msaa is woking. Actually I can even see
it.
I do not know if CMASK should be used even without MSAA turned on, but it seems
on my machine it is never used. I suspect if zmask is for compressed z-buffer
then cmask is for compressed color buffer?
This is also hinted here at this change:
<a href="https://gitlab.freedesktop.org/mesa/mesa/commit/ca2c28859eca83f8fbf1f43616f5ef861e95e8d6">https://gitlab.freedesktop.org/mesa/mesa/commit/ca2c28859eca83f8fbf1f43616f5ef861e95e8d6</a>
Anyways, this is the part that is false always in the if:
r300_resource(fb->cbufs[0]->texture)->tex.cmask_dwords
Actually this might be an issue on its own as in my understanding this code
path would cause a faster code paths when doing MSAA on this card, but I rarely
ever use it anyways nowadays...
If this would happen, it could have lead to the code deflagging the color
channel clear as finished later in the body of the above if:
347 if (r300->screen->cmask_resource == fb->cbufs[0]->texture) {
348 r300_set_clear_color(r300, color);
349 r300_mark_atom_dirty(r300, &r300->cmask_clear);
350 r300_mark_atom_dirty(r300, &r300->gpu_flush);
351 buffers &= ~PIPE_CLEAR_COLOR;
352 }
3.) CBZB clear code path is always taken
----------------------------------------
355 /* Enable CBZB clear. */
356 else if (r300_cbzb_clear_allowed(r300, buffers)) {
357 struct r300_surface *surf = r300_surface(fb->cbufs[0]);
358
359 hyperz->zb_depthclearvalue =
360 r300_depth_clear_cb_value(surf->base.format, color->f);
361
362 width = surf->cbzb_width;
363 height = surf->cbzb_height;
364
365 r300->cbzb_clear = TRUE;
366 r300_mark_fb_state_dirty(r300, R300_CHANGED_HYPERZ_FLAG);
367 }
As far as I understand this should just configure the Zbuffer unit to also
clear the color buffer and both of them clearing it half and half. I will of
course try forcing this to be off, just to see what happens, but it should not
have a side effect for my issue. I am just documenting what happens.
4.) Clearing using the blitter always happen
--------------------------------------------
369 /* Clear. */
370 if (buffers) {
371 /* Clear using the blitter. */
372 /* FIXME: HACKZ TO SAVE FLAGS THAT blitter_clear clears */
373 // bool zdirty = //TODO save vars???
374 r300_blitter_begin(r300, R300_CLEAR);
375 util_blitter_clear(r300->blitter, width, height, 1,
376 buffers, color, depth, stencil);
377 r300_blitter_end(r300);
Sorry for writing into the code randomly here but I am in the middle of trying.
The point is that this is always happening and I think this means that the
blitter unit is always clearing the Z-buffer too and the color buffer is also
cleared with the blitter.
Also the util_blitter_clear call also goes through all the atoms that are made
to be dirty and this makes them not dirty by sending stuff to the kernel part
of the driver.
The r300_emit_zmask_clear is never called it seems
--------------------------------------------------
After this point we just finish the clear function. Originally there was an
"elseif" construct here so surely it could not go forwards after the blitter
was doing its work (only if CMASK kind of color clearing was in operation!) but
even if I comment out the "else" word I am not getting into anything past this:
378 /* TIPP: here maybe not else if, just an if should be present??? */
379 } /*else*/ if (r300->zmask_clear.dirty ||
380 r300->hiz_clear.dirty ||
381 r300->cmask_clear.dirty) {
382 /* Just clear zmask and hiz now, this does not use the standard
draw
383 * procedure. */
384 /* Calculate zmask_clear and hiz_clear atom sizes. */
^^because the flags are not dirty anymore as the blitter had a side effect of
clearing any dirty atom.
Now I am trying to force this part to happen, by saving the values of the
dirtyness of the zmask and hiz atoms and setting the saved value back after the
blitter clear. I wonder what will happen.
If the CMASK kind of color clearing would work, I guess we would end up here
and then call these:
r300_emit_zmask_clear
r300_emit_hiz_clear
I am wondering
==============
- Why the CMASK-related code path not even seem to work even if I use MSAA?
- Why r300_hiz_clear_allowed(r300) always return false for my case?
Further directions
==================
1.) I have found this to be interesting:
src/gallium/drivers/r300/r300_texture_desc.c / r300_setup_hyperz_properties(..)
2.) I will try "forcing" the above idea by saving and reloading the flags
before and after the blitter kind of clear.
3.) Might be a good idea to put a breakpoint in the r300_texture_desc.c here:
402 /* Check whether we have enough HIZ memory. */
403 if (hiz_numdw <= screen->caps.hiz_ram * pipes) {
404 tex->tex.hiz_dwords[i] = hiz_numdw;
405 tex->tex.hiz_stride_in_pixels[i] = stride;
406 } else {
407 tex->tex.hiz_dwords[i] = 0;
408 tex->tex.hiz_stride_in_pixels[i] = 0;
409 }
It seems as if the hiz memory is "not enough"? Weird. I see many of the values
are depending on how many pipes the card have and such. I have no idea how to
get proper info about how many pixel and z pipes a specific card have, but
these latter codes I did not look through properly.</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are the assignee for the bug.</li>
</ul>
</body>
</html>