Merge pull request #12307 from jherico/hotfix/amd_crash

Fix for AMD crashes in QML rendering
This commit is contained in:
John Conklin II 2018-01-31 16:30:53 -08:00 committed by GitHub
commit d37e9af7d4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 12 deletions

View file

@ -565,14 +565,18 @@ void OffscreenQmlSurface::render() {
{ {
// If the most recent texture was unused, we can directly recycle it // If the most recent texture was unused, we can directly recycle it
if (_latestTextureAndFence.first) { auto fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
offscreenTextures.releaseTexture(_latestTextureAndFence);
_latestTextureAndFence = { 0, 0 };
}
_latestTextureAndFence = { texture, glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0) };
// Fence will be used in another thread / context, so a flush is required // Fence will be used in another thread / context, so a flush is required
glFlush(); glFlush();
{
Lock lock(_latestTextureAndFenceMutex);
if (_latestTextureAndFence.first) {
offscreenTextures.releaseTexture(_latestTextureAndFence);
_latestTextureAndFence = { 0, 0 };
}
_latestTextureAndFence = { texture, fence};
}
} }
_quickWindow->resetOpenGLState(); _quickWindow->resetOpenGLState();
@ -583,13 +587,21 @@ void OffscreenQmlSurface::render() {
bool OffscreenQmlSurface::fetchTexture(TextureAndFence& textureAndFence) { bool OffscreenQmlSurface::fetchTexture(TextureAndFence& textureAndFence) {
textureAndFence = { 0, 0 }; textureAndFence = { 0, 0 };
// Lock free early check
if (0 == _latestTextureAndFence.first) { if (0 == _latestTextureAndFence.first) {
return false; return false;
} }
// Ensure writes to the latest texture are complete before before returning it for reading // Ensure writes to the latest texture are complete before before returning it for reading
textureAndFence = _latestTextureAndFence; {
_latestTextureAndFence = { 0, 0 }; Lock lock(_latestTextureAndFenceMutex);
// Double check inside the lock
if (0 == _latestTextureAndFence.first) {
return false;
}
textureAndFence = _latestTextureAndFence;
_latestTextureAndFence = { 0, 0 };
}
return true; return true;
} }
@ -797,10 +809,13 @@ void OffscreenQmlSurface::resize(const QSize& newSize_, bool forceResize) {
// Release hold on the textures of the old size // Release hold on the textures of the old size
if (uvec2() != _size) { if (uvec2() != _size) {
// If the most recent texture was unused, we can directly recycle it {
if (_latestTextureAndFence.first) { Lock lock(_latestTextureAndFenceMutex);
offscreenTextures.releaseTexture(_latestTextureAndFence); // If the most recent texture was unused, we can directly recycle it
_latestTextureAndFence = { 0, 0 }; if (_latestTextureAndFence.first) {
offscreenTextures.releaseTexture(_latestTextureAndFence);
_latestTextureAndFence = { 0, 0 };
}
} }
offscreenTextures.releaseSize(_size); offscreenTextures.releaseSize(_size);
} }

View file

@ -167,6 +167,9 @@ public slots:
bool handlePointerEvent(const PointerEvent& event, class QTouchDevice& device, bool release = false); bool handlePointerEvent(const PointerEvent& event, class QTouchDevice& device, bool release = false);
private: private:
using Mutex = std::mutex;
using Lock = std::unique_lock<std::mutex>;
QQuickWindow* _quickWindow { nullptr }; QQuickWindow* _quickWindow { nullptr };
QMyQuickRenderControl* _renderControl{ nullptr }; QMyQuickRenderControl* _renderControl{ nullptr };
QQmlContext* _qmlContext { nullptr }; QQmlContext* _qmlContext { nullptr };
@ -185,6 +188,7 @@ private:
#endif #endif
// Texture management // Texture management
Mutex _latestTextureAndFenceMutex;
TextureAndFence _latestTextureAndFence { 0, 0 }; TextureAndFence _latestTextureAndFence { 0, 0 };
bool _render { false }; bool _render { false };