Commit 46c13a15 by Kenneth Russell

Add workaround for flushing before readPixels.

This has been found necessary on the D3D11 backend on AMD GPUs, and on the D3D9 backend on all GPUs. Tested an earlier version of this patch overnight on one of the affected Windows AMD bots; it eliminated the flakiness observed on one of the WebGL conformance tests. BUG=491419 Change-Id: I668493eb5ec109b5e0650c154dc97b786e0745bd Reviewed-on: https://chromium-review.googlesource.com/278265Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarKenneth Russell <kbr@chromium.org>
parent 322653bf
...@@ -44,7 +44,8 @@ struct Workarounds ...@@ -44,7 +44,8 @@ struct Workarounds
: mrtPerfWorkaround(false), : mrtPerfWorkaround(false),
setDataFasterThanImageUpload(false), setDataFasterThanImageUpload(false),
zeroMaxLodWorkaround(false), zeroMaxLodWorkaround(false),
useInstancedPointSpriteEmulation(false) useInstancedPointSpriteEmulation(false),
finishBeforeReadPixels(false)
{} {}
// On some systems, having extra rendertargets than necessary slows down the shader. // On some systems, having extra rendertargets than necessary slows down the shader.
...@@ -67,6 +68,12 @@ struct Workarounds ...@@ -67,6 +68,12 @@ struct Workarounds
// To work around this, D3D11 FL9_3 has to use a different pointsprite // To work around this, D3D11 FL9_3 has to use a different pointsprite
// emulation that is implemented using instanced quads. // emulation that is implemented using instanced quads.
bool useInstancedPointSpriteEmulation; bool useInstancedPointSpriteEmulation;
// On some GPUs, race conditions have been observed during ReadPixels where GPU rendering is
// completing at the same time that the pixels are being mapped. This workaround governs whether
// a renderer finish is performed just before the readback operation. For performance reasons,
// it must not be done when using a pixel pack buffer.
bool finishBeforeReadPixels;
}; };
} }
......
...@@ -258,6 +258,15 @@ gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle ...@@ -258,6 +258,15 @@ gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle
return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels"); return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels");
} }
if (!packState.pixelBuffer.get() && mRenderer->getWorkarounds().finishBeforeReadPixels)
{
gl::Error error = mRenderer->finish();
if (error.isError())
{
return error;
}
}
GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type); GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, 0); GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, 0);
......
...@@ -3667,7 +3667,7 @@ void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureC ...@@ -3667,7 +3667,7 @@ void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureC
Workarounds Renderer11::generateWorkarounds() const Workarounds Renderer11::generateWorkarounds() const
{ {
return d3d11::GenerateWorkarounds(mRenderer11DeviceCaps.featureLevel); return d3d11::GenerateWorkarounds(this);
} }
void Renderer11::setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv) void Renderer11::setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv)
......
...@@ -260,7 +260,7 @@ class Renderer11 : public RendererD3D ...@@ -260,7 +260,7 @@ class Renderer11 : public RendererD3D
bool colorBlit, bool depthBlit, bool stencilBlit); bool colorBlit, bool depthBlit, bool stencilBlit);
bool isES3Capable() const; bool isES3Capable() const;
const Renderer11DeviceCaps &getRenderer11DeviceCaps() { return mRenderer11DeviceCaps; }; const Renderer11DeviceCaps &getRenderer11DeviceCaps() const { return mRenderer11DeviceCaps; }
RendererClass getRendererClass() const override { return RENDERER_D3D11; } RendererClass getRendererClass() const override { return RENDERER_D3D11; }
......
...@@ -1236,13 +1236,15 @@ HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) ...@@ -1236,13 +1236,15 @@ HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name)
#endif #endif
} }
Workarounds GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel) Workarounds GenerateWorkarounds(const Renderer11 *renderer)
{ {
D3D_FEATURE_LEVEL featureLevel = renderer->getRenderer11DeviceCaps().featureLevel;
Workarounds workarounds; Workarounds workarounds;
workarounds.mrtPerfWorkaround = true; workarounds.mrtPerfWorkaround = true;
workarounds.setDataFasterThanImageUpload = true; workarounds.setDataFasterThanImageUpload = true;
workarounds.zeroMaxLodWorkaround = (featureLevel <= D3D_FEATURE_LEVEL_9_3); workarounds.zeroMaxLodWorkaround = (featureLevel <= D3D_FEATURE_LEVEL_9_3);
workarounds.useInstancedPointSpriteEmulation = (featureLevel <= D3D_FEATURE_LEVEL_9_3); workarounds.useInstancedPointSpriteEmulation = (featureLevel <= D3D_FEATURE_LEVEL_9_3);
workarounds.finishBeforeReadPixels = renderer->getVendorId() == VENDOR_ID_AMD;
return workarounds; return workarounds;
} }
......
...@@ -24,6 +24,7 @@ class FramebufferAttachment; ...@@ -24,6 +24,7 @@ class FramebufferAttachment;
namespace rx namespace rx
{ {
class Renderer11;
class RenderTarget11; class RenderTarget11;
struct Workarounds; struct Workarounds;
struct Renderer11DeviceCaps; struct Renderer11DeviceCaps;
...@@ -278,7 +279,7 @@ void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, c ...@@ -278,7 +279,7 @@ void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, c
} }
} }
Workarounds GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel); Workarounds GenerateWorkarounds(const Renderer11 *renderer);
} }
......
...@@ -581,6 +581,9 @@ Workarounds GenerateWorkarounds() ...@@ -581,6 +581,9 @@ Workarounds GenerateWorkarounds()
workarounds.mrtPerfWorkaround = true; workarounds.mrtPerfWorkaround = true;
workarounds.setDataFasterThanImageUpload = false; workarounds.setDataFasterThanImageUpload = false;
workarounds.useInstancedPointSpriteEmulation = false; workarounds.useInstancedPointSpriteEmulation = false;
// Flakiness has been observed in WebGL conformance tests using
// ReadPixels on all vendors' GPUs with the D3D9 backend.
workarounds.finishBeforeReadPixels = true;
return workarounds; return workarounds;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment