New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 678637 link

Starred by 1 user

Issue metadata

Status: WontFix
Owner: ----
Closed: Feb 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: All
Pri: 3
Type: Bug



Sign in to add a comment

Some issues for clear_state_dirty in GLES2DecoderImpl in command buffer

Project Member Reported by yunchao...@intel.com, Jan 5 2017

Issue description

It seems to me that there may be some mistake in the design of clear_state_dirty.

clear_state_dirty is set to true when color/depth/stencil masks are changed when we call 
ColorMask/DepthMask/StencilMask/StencilMaskSeparate (or enable/disable depth/stencil test is changed). It will store the masks, but don't call into driver immediately. When clear/draw APIs are called, it will call into driver if the masks are different from the cached mask, then update the cached masks. This is reasonable. 

Besides, when we initiate a texture to zero by glClear, or when we need to draw/clear a texture ( in order to workaround some bug, or emulate some color formats), we need to set clearcolor and masks, so we need to set clear_state_dirty and RestoreClearState afterwards. This is reasonable too.

However, when fbo is changed by {bind|delete}Framebuffer, or fbo image is changed by
framebuffer{Texture2D|TextureLayer|Renderbuffer}, the clear_state_dirty will be set
to true. I think it is unnecessary. Because color/depth/stencil masks are per context, 
not per fbo. 

In addition, when the image of fbo attachment is updated by TexImage2D, TexStorage2D, 
or CompressedTexImage2D, the clear_state_dirty is set to true too. It is unnecessary too.  
 
Please correct me if I misunderstood clear_state_dirty.

see the small patch at https://codereview.chromium.org/2613793003/.

Comment 2 by zmo@chromium.org, Jan 5 2017

Owner: yunchao...@intel.com
Status: Assigned (was: Untriaged)
I think your understanding is correct. We set clear_state_dirty_ more often than necessary. Likely RestoreClearState isn't a heavy operation, so we never notice this. That said, if you can clean this up, it's definitely good for code health and readability.

Comment 3 by zmo@chromium.org, Jan 5 2017

Cc: vmi...@chromium.org

Comment 4 by zmo@chromium.org, Jan 5 2017

Sorry I spoke before I read the code carefully.

If you look at GLES2DecoderImpl::ApplyDirtyState(), where you enable the masks depending on if the fbo contains the corresponding attachments. i.e., if we don't have depth image attached, then we don't enable depth even if the user called DepthMask(true).

Therefore, the fbo change change does affect the clear_state_dirty_.

For example, if you set depth mask to true, but no depth image is attached.  Now you draw, ApplyDirtyState() will leave depth mask to be false.  Now you attach a depth image, and draw again, if clear_state_dirty_ isn't set to true, then ApplyDirtyState will do nothing and depth mask remains false, which is a mistake.

Please close this bug if you agree with my analysis.
Thanks for your explanation, @zmo. But I have different opinion. For the situation you said, the question is that why we need to enable/disable depth/stencil test according to whether we have depth/stencil attachment in fbo? 

Per my understanding, all of the states (masks, enable or disable depth/stencil test) are per context, not per fbo. So I think we should not define framebuffer_state_.clear_state_dirty in framebuffer_manager.cc, but to define state_.clear_state_dirty in context_state.cc 

I wonder that do we have a driver bug if we enable depth/stencil test but there is no depth/stencil attachment? If that is true, maybe we should do this in a workaround for specific driver, instead of enabling/disabling depth/stencil test in ApplyDirtyState. I indeed see that we frequently set clear_state_dirty and call ApplyDirtyState, although it doesn't call into driver every time because of the cache mechanism.
BTW, the patch at https://codereview.chromium.org/2613793003/ remove the code snippet to set clear_state_dirty when the image pixels are changed by TexImage2D, TexStorage2D, CompressedTexImage2D. I think it is not necessary. 

Even in the current code design, if an image is attached/unattached to fbo, clear_state_dirty have been set in framebuffer{Textuer2D|TextureLayer} already. It is not necessary to set clear_state_dirty when we update the image pixels by TexImage2D...

Comment 7 by zmo@chromium.org, Jan 6 2017

Note that DecoderFramebufferState is per FramebufferManager, not per Framebuffer, so it is per context.

As for why we enable/disable depth/stencil, the command buffer's basic design philosophy is we don't trust the drivers so we always try to be on the cautious side if it's not affecting perf. I don't think we need to revisit this and put it behind a driver bug workaround.
Cc: yang...@intel.com
Ah, you are correct, @zmo. clear_state_dirty is per context in current code. 

However, I don't think it is necessary to set or unset clear_state_dirty according to whether we have color/depth/stencil buffer in current fbo. If we remove these unnecessary code, all WebGL CTS can pass, see the change at: https://codereview.chromium.org/2612523003/ (The failures are in gpu_unittests, because some gl operations will not be called any more when clear_dirty_state is removed). 

In the current code, there are many call sites to ApplyDirtyState() and gl operations to enable/disable masks (I have added some printf to check about this in my local machine). If we remove the set/unset code, almost all call sites to ApplyDirtyState() and gl operations to enable/disable masks are gone for most conformance tests. So the code cleanup can improve performance.

The other reason that I want to remove most of the clear_state_dirty: I need a flag like fboimage_state_dirty to detect feedback loop when fbo images are changed by bindFramebuffer/deleteFramebuffer/framebufferTexture2D/framebufferTextureLayer/drawBuffers/framebufferRenderbuffer/etc. You see, This flag will be set/unset in functions in which we set clear_state_dirty too. If we have 2 flags, it seems to be confusing... 

So I think this code cleanup about clear_state_dirty may be reasonable, WDYT?

Comment 9 by zmo@chromium.org, Jan 10 2017

I am not worried about 2 flags being confusing, but this extra optimization with clear_state_dirty does feel adding more burden than benefits.  If we won't trigger any driver bugs, then I am OK with removing it when fbo/texture/renderbuffer change.
OK, I will have a try in these two days.
Cc: yunchao...@intel.com
Owner: ----
Status: WontFix (was: Assigned)
Sorry. It is a long time to revisit this issue.

I tried to remove clear_state_dirty in command buffer to remove redundant gl call sites. It indeed works for all WebGL CTS. All webgl cts can pass on trybots.

However, the gpu_unittests have lots of expectations to call these gl operations. If the gl call sites to driver are removed, the expectations will not be satisfied, making the corresponding gpu_unittest failed. And the code in gpu_unittests related to the expectation functions scattered here and there. It is rather time-consuming to remove all these expectations in gpu_unittests. So I would not fix this issue.

Please re-open this one if anyone want to fix this issue.

Sign in to add a comment