From 0be1f82bbc53a653af49d041b1f1d736892fe83b Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 14 Oct 2016 16:25:23 -0700 Subject: [PATCH] Fix AMD crash caused by missing glFlush --- libraries/gl/src/gl/TextureRecycler.cpp | 46 +++++++++++++---------- libraries/gl/src/gl/TextureRecycler.h | 3 ++ libraries/gpu-gl/src/gpu/gl/GLBackend.cpp | 16 ++++++-- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/libraries/gl/src/gl/TextureRecycler.cpp b/libraries/gl/src/gl/TextureRecycler.cpp index 4438e158c5..04cd38f156 100644 --- a/libraries/gl/src/gl/TextureRecycler.cpp +++ b/libraries/gl/src/gl/TextureRecycler.cpp @@ -37,27 +37,35 @@ void TextureRecycler::clear() { _allTextures.clear(); } +void TextureRecycler::addTexture() { + uint32_t newTexture; + glGenTextures(1, &newTexture); + glBindTexture(GL_TEXTURE_2D, newTexture); + if (_useMipmaps) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0f); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -0.2f); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0f); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, _size.x, _size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + _allTextures.emplace(std::piecewise_construct, std::forward_as_tuple(newTexture), std::forward_as_tuple(newTexture, _size)); + _readyTextures.push(newTexture); +} + uint32_t TextureRecycler::getNextTexture() { + while (_allTextures.size() < _textureCount) { + addTexture(); + } + if (_readyTextures.empty()) { - uint32_t newTexture; - glGenTextures(1, &newTexture); - glBindTexture(GL_TEXTURE_2D, newTexture); - if (_useMipmaps) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0f); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -0.2f); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0f); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, _size.x, _size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - _allTextures.emplace(std::piecewise_construct, std::forward_as_tuple(newTexture), std::forward_as_tuple(newTexture, _size)); - _readyTextures.push(newTexture); + addTexture(); } uint32_t result = _readyTextures.front(); diff --git a/libraries/gl/src/gl/TextureRecycler.h b/libraries/gl/src/gl/TextureRecycler.h index 46cbcad219..b3e61fb67a 100644 --- a/libraries/gl/src/gl/TextureRecycler.h +++ b/libraries/gl/src/gl/TextureRecycler.h @@ -19,11 +19,13 @@ class TextureRecycler { public: TextureRecycler(bool useMipmaps) : _useMipmaps(useMipmaps) {} void setSize(const uvec2& size); + void setTextureCount(uint8_t textureCount); void clear(); uint32_t getNextTexture(); void recycleTexture(uint32_t texture); private: + void addTexture(); struct TexInfo { const uint32_t _tex{ 0 }; @@ -42,6 +44,7 @@ private: Queue _readyTextures; uvec2 _size{ 1920, 1080 }; bool _useMipmaps; + uint8_t _textureCount { 3 }; }; #endif diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp index 3c34765011..2e1084e581 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp @@ -663,9 +663,19 @@ void GLBackend::recycle() const { Lock lock(_trashMutex); std::swap(_externalTexturesTrash, externalTexturesTrash); } - for (auto pair : externalTexturesTrash) { - auto fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); - pair.second(pair.first, fence); + if (!externalTexturesTrash.empty()) { + std::vector fences; + fences.resize(externalTexturesTrash.size()); + for (size_t i = 0; i < externalTexturesTrash.size(); ++i) { + fences[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + } + // External texture fences will be read in another thread/context, so we need a flush + glFlush(); + size_t index = 0; + for (auto pair : externalTexturesTrash) { + auto fence = fences[index++]; + pair.second(pair.first, fence); + } } }