mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-26 03:15:21 +02:00
Fix sparse texture deallocation
This commit is contained in:
parent
64cb45240d
commit
5734332150
4 changed files with 60 additions and 38 deletions
|
@ -593,7 +593,23 @@ void GLBackend::releaseQuery(GLuint id) const {
|
||||||
_queriesTrash.push_back(id);
|
_queriesTrash.push_back(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLBackend::releaseLambda(const std::function<void()> lambda) const {
|
||||||
|
Lock lock(_trashMutex);
|
||||||
|
_lambdasTrash.push_back(lambda);
|
||||||
|
}
|
||||||
|
|
||||||
void GLBackend::recycle() const {
|
void GLBackend::recycle() const {
|
||||||
|
{
|
||||||
|
std::list<std::function<void()>> lamdbasTrash;
|
||||||
|
{
|
||||||
|
Lock lock(_trashMutex);
|
||||||
|
std::swap(_lambdasTrash, lamdbasTrash);
|
||||||
|
}
|
||||||
|
for (auto lambda : lamdbasTrash) {
|
||||||
|
lambda();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
std::vector<GLuint> ids;
|
std::vector<GLuint> ids;
|
||||||
std::list<std::pair<GLuint, Size>> buffersTrash;
|
std::list<std::pair<GLuint, Size>> buffersTrash;
|
||||||
|
|
|
@ -175,6 +175,7 @@ public:
|
||||||
virtual void releaseShader(GLuint id) const;
|
virtual void releaseShader(GLuint id) const;
|
||||||
virtual void releaseProgram(GLuint id) const;
|
virtual void releaseProgram(GLuint id) const;
|
||||||
virtual void releaseQuery(GLuint id) const;
|
virtual void releaseQuery(GLuint id) const;
|
||||||
|
virtual void releaseLambda(const std::function<void()> lambda) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -197,6 +198,7 @@ protected:
|
||||||
mutable std::list<GLuint> _shadersTrash;
|
mutable std::list<GLuint> _shadersTrash;
|
||||||
mutable std::list<GLuint> _programsTrash;
|
mutable std::list<GLuint> _programsTrash;
|
||||||
mutable std::list<GLuint> _queriesTrash;
|
mutable std::list<GLuint> _queriesTrash;
|
||||||
|
mutable std::list<std::function<void()>> _lambdasTrash;
|
||||||
|
|
||||||
void renderPassTransfer(const Batch& batch);
|
void renderPassTransfer(const Batch& batch);
|
||||||
void renderPassDraw(const Batch& batch);
|
void renderPassDraw(const Batch& batch);
|
||||||
|
|
|
@ -155,7 +155,6 @@ GLTexture::~GLTexture() {
|
||||||
auto backend = _backend.lock();
|
auto backend = _backend.lock();
|
||||||
if (backend) {
|
if (backend) {
|
||||||
backend->releaseTexture(_id, _size);
|
backend->releaseTexture(_id, _size);
|
||||||
backend->recycle();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Backend::updateTextureGPUVirtualMemoryUsage(_virtualSize, 0);
|
Backend::updateTextureGPUVirtualMemoryUsage(_virtualSize, 0);
|
||||||
|
|
|
@ -30,6 +30,7 @@ static bool enableSparseTextures = !QProcessEnvironment::systemEnvironment().con
|
||||||
|
|
||||||
// Allocate 1 MB of buffer space for paged transfers
|
// Allocate 1 MB of buffer space for paged transfers
|
||||||
#define DEFAULT_PAGE_BUFFER_SIZE (1024*1024)
|
#define DEFAULT_PAGE_BUFFER_SIZE (1024*1024)
|
||||||
|
#define DEFAULT_GL_PIXEL_ALIGNMENT 4
|
||||||
|
|
||||||
using GL45Texture = GL45Backend::GL45Texture;
|
using GL45Texture = GL45Backend::GL45Texture;
|
||||||
|
|
||||||
|
@ -39,7 +40,6 @@ using TextureTypeFormat = std::pair<GLenum, GLenum>;
|
||||||
std::map<TextureTypeFormat, std::vector<uvec3>> sparsePageDimensionsByFormat;
|
std::map<TextureTypeFormat, std::vector<uvec3>> sparsePageDimensionsByFormat;
|
||||||
Mutex sparsePageDimensionsByFormatMutex;
|
Mutex sparsePageDimensionsByFormatMutex;
|
||||||
|
|
||||||
|
|
||||||
static std::vector<uvec3> getPageDimensionsForFormat(const TextureTypeFormat& typeFormat) {
|
static std::vector<uvec3> getPageDimensionsForFormat(const TextureTypeFormat& typeFormat) {
|
||||||
{
|
{
|
||||||
Lock lock(sparsePageDimensionsByFormatMutex);
|
Lock lock(sparsePageDimensionsByFormatMutex);
|
||||||
|
@ -64,7 +64,7 @@ static std::vector<uvec3> getPageDimensionsForFormat(const TextureTypeFormat& ty
|
||||||
for (GLint i = 0; i < count; ++i) {
|
for (GLint i = 0; i < count; ++i) {
|
||||||
result[i] = uvec3(x[i], y[i], z[i]);
|
result[i] = uvec3(x[i], y[i], z[i]);
|
||||||
}
|
}
|
||||||
qDebug() << "Got " << count << " page sizes";
|
qCDebug(gpugl45logging) << "Got " << count << " page sizes";
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -212,7 +212,6 @@ bool TransferState::increment() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEFAULT_GL_PIXEL_ALIGNMENT 4
|
|
||||||
void TransferState::populatePage(std::vector<uint8_t>& buffer) {
|
void TransferState::populatePage(std::vector<uint8_t>& buffer) {
|
||||||
uvec3 pageSize = currentPageSize();
|
uvec3 pageSize = currentPageSize();
|
||||||
auto bytesPerPageLine = _bytesPerPixel * pageSize.x;
|
auto bytesPerPageLine = _bytesPerPixel * pageSize.x;
|
||||||
|
@ -254,35 +253,41 @@ GL45Texture::GL45Texture(const std::weak_ptr<GLBackend>& backend, const Texture&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Destructors get called on the main thread, potentially without a context active. We need to queue the
|
||||||
|
// deallocation of the sparse pages for this content.
|
||||||
GL45Texture::~GL45Texture() {
|
GL45Texture::~GL45Texture() {
|
||||||
if (_sparseInfo._sparse) {
|
|
||||||
auto mipLevels = usedMipLevels();
|
|
||||||
|
|
||||||
{
|
if (_sparseInfo._sparse) {
|
||||||
Lock lock(texturesByMipCountsMutex);
|
auto backend = _backend.lock();
|
||||||
if (texturesByMipCounts.count(mipLevels)) {
|
if (backend) {
|
||||||
auto& textures = texturesByMipCounts[mipLevels];
|
auto id = _id;
|
||||||
textures.erase(this);
|
auto mipLevels = usedMipLevels();
|
||||||
if (textures.empty()) {
|
{
|
||||||
texturesByMipCounts.erase(mipLevels);
|
Lock lock(texturesByMipCountsMutex);
|
||||||
|
if (texturesByMipCounts.count(mipLevels)) {
|
||||||
|
auto& textures = texturesByMipCounts[mipLevels];
|
||||||
|
textures.erase(this);
|
||||||
|
if (textures.empty()) {
|
||||||
|
texturesByMipCounts.erase(mipLevels);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
auto maxSparseMip = std::min<uint16_t>(_maxMip, _sparseInfo._maxSparseLevel);
|
auto maxSparseMip = std::min<uint16_t>(_maxMip, _sparseInfo._maxSparseLevel);
|
||||||
uint8_t maxFace = (uint8_t)((_target == GL_TEXTURE_CUBE_MAP) ? GLTexture::CUBE_NUM_FACES : 1);
|
uint8_t maxFace = (uint8_t)((_target == GL_TEXTURE_CUBE_MAP) ? GLTexture::CUBE_NUM_FACES : 1);
|
||||||
for (uint16_t mipLevel = _minMip; mipLevel <= maxSparseMip; ++mipLevel) {
|
for (uint16_t mipLevel = _minMip; mipLevel <= maxSparseMip; ++mipLevel) {
|
||||||
auto mipDimensions = _gpuObject.evalMipDimensions(mipLevel);
|
auto mipDimensions = _gpuObject.evalMipDimensions(mipLevel);
|
||||||
auto deallocatedPages = _sparseInfo.getPageCount(mipDimensions);
|
backend->releaseLambda([=] {
|
||||||
for (uint8_t face = 0; face < maxFace; ++face) {
|
glTexturePageCommitmentEXT(id, mipLevel, 0, 0, 0, mipDimensions.x, mipDimensions.y, maxFace, GL_FALSE);
|
||||||
glTexturePageCommitmentEXT(_id, mipLevel, 0, 0, face, mipDimensions.x, mipDimensions.y, mipDimensions.z, GL_FALSE);
|
});
|
||||||
|
auto deallocatedPages = _sparseInfo.getPageCount(mipDimensions) * maxFace;
|
||||||
assert(deallocatedPages <= _allocatedPages);
|
assert(deallocatedPages <= _allocatedPages);
|
||||||
_allocatedPages -= deallocatedPages;
|
_allocatedPages -= deallocatedPages;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != _allocatedPages) {
|
if (0 != _allocatedPages) {
|
||||||
qWarning() << "Allocated pages remaining " << _id << " " << _allocatedPages;
|
qCWarning(gpugl45logging) << "Allocated pages remaining " << _id << " " << _allocatedPages;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -292,7 +297,7 @@ void GL45Texture::withPreservedTexture(std::function<void()> f) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GL45Texture::generateMips() const {
|
void GL45Texture::generateMips() const {
|
||||||
qDebug() << "Generating mipmaps for " << _gpuObject.source().c_str();
|
qCDebug(gpugl45logging) << "Generating mipmaps for " << _gpuObject.source().c_str();
|
||||||
glGenerateTextureMipmap(_id);
|
glGenerateTextureMipmap(_id);
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
@ -337,7 +342,7 @@ bool GL45Texture::continueTransfer() {
|
||||||
|
|
||||||
if (_sparseInfo._sparse && _transferState._mipLevel <= _sparseInfo._maxSparseLevel) {
|
if (_sparseInfo._sparse && _transferState._mipLevel <= _sparseInfo._maxSparseLevel) {
|
||||||
if (_allocatedPages > _sparseInfo._maxPages) {
|
if (_allocatedPages > _sparseInfo._maxPages) {
|
||||||
qWarning() << "Exceeded max page allocation!";
|
qCWarning(gpugl45logging) << "Exceeded max page allocation!";
|
||||||
}
|
}
|
||||||
glTexturePageCommitmentEXT(_id, _transferState._mipLevel,
|
glTexturePageCommitmentEXT(_id, _transferState._mipLevel,
|
||||||
offset.x, offset.y, _transferState._face,
|
offset.x, offset.y, _transferState._face,
|
||||||
|
@ -373,7 +378,7 @@ bool GL45Texture::continueTransfer() {
|
||||||
auto mipExpectedPages = _sparseInfo.getPageCount(mipDimensions);
|
auto mipExpectedPages = _sparseInfo.getPageCount(mipDimensions);
|
||||||
auto newPages = _allocatedPages - _lastMipAllocatedPages;
|
auto newPages = _allocatedPages - _lastMipAllocatedPages;
|
||||||
if (newPages != mipExpectedPages) {
|
if (newPages != mipExpectedPages) {
|
||||||
qWarning() << "Unexpected page allocation size... " << newPages << " " << mipExpectedPages;
|
qCWarning(gpugl45logging) << "Unexpected page allocation size... " << newPages << " " << mipExpectedPages;
|
||||||
}
|
}
|
||||||
_lastMipAllocatedPages = _allocatedPages;
|
_lastMipAllocatedPages = _allocatedPages;
|
||||||
}
|
}
|
||||||
|
@ -426,12 +431,12 @@ void GL45Texture::stripToMip(uint16_t newMinMip) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newMinMip < _minMip) {
|
if (newMinMip < _minMip) {
|
||||||
qWarning() << "Cannot decrease the min mip";
|
qCWarning(gpugl45logging) << "Cannot decrease the min mip";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newMinMip > _sparseInfo._maxSparseLevel) {
|
if (newMinMip > _sparseInfo._maxSparseLevel) {
|
||||||
qWarning() << "Cannot increase the min mip into the mip tail";
|
qCWarning(gpugl45logging) << "Cannot increase the min mip into the mip tail";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,7 +453,7 @@ void GL45Texture::stripToMip(uint16_t newMinMip) {
|
||||||
|
|
||||||
// If we weren't generating mips before, we need to now that we're stripping down mip levels.
|
// If we weren't generating mips before, we need to now that we're stripping down mip levels.
|
||||||
if (!_gpuObject.isAutogenerateMips()) {
|
if (!_gpuObject.isAutogenerateMips()) {
|
||||||
qDebug() << "Force mip generation for texture";
|
qCDebug(gpugl45logging) << "Force mip generation for texture";
|
||||||
glGenerateTextureMipmap(_id);
|
glGenerateTextureMipmap(_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,9 +479,9 @@ void GL45Texture::stripToMip(uint16_t newMinMip) {
|
||||||
updateSize();
|
updateSize();
|
||||||
size_t newSize = _size;
|
size_t newSize = _size;
|
||||||
if (newSize > oldSize) {
|
if (newSize > oldSize) {
|
||||||
qDebug() << "WTF";
|
qCDebug(gpugl45logging) << "WTF";
|
||||||
qDebug() << "\told size " << oldSize;
|
qCDebug(gpugl45logging) << "\told size " << oldSize;
|
||||||
qDebug() << "\tnew size " << newSize;
|
qCDebug(gpugl45logging) << "\tnew size " << newSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-insert into the texture-by-mips map if appropriate
|
// Re-insert into the texture-by-mips map if appropriate
|
||||||
|
@ -512,18 +517,18 @@ void GL45Backend::derezTextures() const {
|
||||||
|
|
||||||
Lock lock(texturesByMipCountsMutex);
|
Lock lock(texturesByMipCountsMutex);
|
||||||
if (texturesByMipCounts.empty()) {
|
if (texturesByMipCounts.empty()) {
|
||||||
qDebug() << "No available textures to derez";
|
qCDebug(gpugl45logging) << "No available textures to derez";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mipLevel = texturesByMipCounts.rbegin()->first;
|
auto mipLevel = texturesByMipCounts.rbegin()->first;
|
||||||
if (mipLevel <= 1) {
|
if (mipLevel <= 1) {
|
||||||
qDebug() << "Max mip levels " << mipLevel;
|
qCDebug(gpugl45logging) << "Max mip levels " << mipLevel;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Allowed texture memory " << Texture::getAllowedGPUMemoryUsage();
|
qCDebug(gpugl45logging) << "Allowed texture memory " << Texture::getAllowedGPUMemoryUsage();
|
||||||
qDebug() << "Used texture memory " << Context::getTextureGPUMemoryUsage();
|
qCDebug(gpugl45logging) << "Used texture memory " << Context::getTextureGPUMemoryUsage();
|
||||||
|
|
||||||
GL45Texture* targetTexture = nullptr;
|
GL45Texture* targetTexture = nullptr;
|
||||||
{
|
{
|
||||||
|
@ -533,5 +538,5 @@ void GL45Backend::derezTextures() const {
|
||||||
}
|
}
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
targetTexture->derez();
|
targetTexture->derez();
|
||||||
qDebug() << "New Used texture memory " << Context::getTextureGPUMemoryUsage();
|
qCDebug(gpugl45logging) << "New Used texture memory " << Context::getTextureGPUMemoryUsage();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue