mirror of
https://github.com/lubosz/overte.git
synced 2025-08-07 18:21:16 +02:00
Merge pull request #9014 from jherico/texture_derez
Re-enable downsampling for non-sparse textures
This commit is contained in:
commit
f5fd4bf8d1
10 changed files with 121 additions and 85 deletions
|
@ -387,21 +387,9 @@ Menu::Menu() {
|
||||||
});
|
});
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#define MIN_CORES_FOR_INCREMENTAL_TEXTURES 5
|
// Developer > Render > Enable Sparse Textures
|
||||||
bool recommendedIncrementalTransfers = (QThread::idealThreadCount() >= MIN_CORES_FOR_INCREMENTAL_TEXTURES);
|
|
||||||
bool recommendedSparseTextures = recommendedIncrementalTransfers;
|
|
||||||
|
|
||||||
qDebug() << "[TEXTURE TRANSFER SUPPORT]"
|
|
||||||
<< "\n\tidealThreadCount:" << QThread::idealThreadCount()
|
|
||||||
<< "\n\tRECOMMENDED enableSparseTextures:" << recommendedSparseTextures
|
|
||||||
<< "\n\tRECOMMENDED enableIncrementalTextures:" << recommendedIncrementalTransfers;
|
|
||||||
|
|
||||||
gpu::Texture::setEnableIncrementalTextureTransfers(recommendedIncrementalTransfers);
|
|
||||||
gpu::Texture::setEnableSparseTextures(recommendedSparseTextures);
|
|
||||||
|
|
||||||
// Developer > Render > Enable Dynamic Texture Management
|
|
||||||
{
|
{
|
||||||
auto action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::EnableDynamicTextureManagement, 0, recommendedSparseTextures);
|
auto action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::SparseTextureManagement, 0, gpu::Texture::getEnableSparseTextures());
|
||||||
connect(action, &QAction::triggered, [&](bool checked) {
|
connect(action, &QAction::triggered, [&](bool checked) {
|
||||||
qDebug() << "[TEXTURE TRANSFER SUPPORT] --- Enable Dynamic Texture Management menu option:" << checked;
|
qDebug() << "[TEXTURE TRANSFER SUPPORT] --- Enable Dynamic Texture Management menu option:" << checked;
|
||||||
gpu::Texture::setEnableSparseTextures(checked);
|
gpu::Texture::setEnableSparseTextures(checked);
|
||||||
|
@ -410,7 +398,7 @@ Menu::Menu() {
|
||||||
|
|
||||||
// Developer > Render > Enable Incremental Texture Transfer
|
// Developer > Render > Enable Incremental Texture Transfer
|
||||||
{
|
{
|
||||||
auto action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::EnableIncrementalTextureTransfer, 0, recommendedIncrementalTransfers);
|
auto action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::IncrementalTextureTransfer, 0, gpu::Texture::getEnableIncrementalTextureTransfers());
|
||||||
connect(action, &QAction::triggered, [&](bool checked) {
|
connect(action, &QAction::triggered, [&](bool checked) {
|
||||||
qDebug() << "[TEXTURE TRANSFER SUPPORT] --- Enable Incremental Texture Transfer menu option:" << checked;
|
qDebug() << "[TEXTURE TRANSFER SUPPORT] --- Enable Incremental Texture Transfer menu option:" << checked;
|
||||||
gpu::Texture::setEnableIncrementalTextureTransfers(checked);
|
gpu::Texture::setEnableIncrementalTextureTransfers(checked);
|
||||||
|
|
|
@ -97,8 +97,6 @@ namespace MenuOption {
|
||||||
const QString EchoLocalAudio = "Echo Local Audio";
|
const QString EchoLocalAudio = "Echo Local Audio";
|
||||||
const QString EchoServerAudio = "Echo Server Audio";
|
const QString EchoServerAudio = "Echo Server Audio";
|
||||||
const QString EnableCharacterController = "Enable avatar collisions";
|
const QString EnableCharacterController = "Enable avatar collisions";
|
||||||
const QString EnableIncrementalTextureTransfer = "Enable Incremental Texture Transfer";
|
|
||||||
const QString EnableDynamicTextureManagement = "Enable Dynamic Texture Management";
|
|
||||||
const QString EnableInverseKinematics = "Enable Inverse Kinematics";
|
const QString EnableInverseKinematics = "Enable Inverse Kinematics";
|
||||||
const QString ExpandMyAvatarSimulateTiming = "Expand /myAvatar/simulation";
|
const QString ExpandMyAvatarSimulateTiming = "Expand /myAvatar/simulation";
|
||||||
const QString ExpandMyAvatarTiming = "Expand /myAvatar";
|
const QString ExpandMyAvatarTiming = "Expand /myAvatar";
|
||||||
|
@ -114,6 +112,7 @@ namespace MenuOption {
|
||||||
const QString FrameTimer = "Show Timer";
|
const QString FrameTimer = "Show Timer";
|
||||||
const QString FullscreenMirror = "Mirror";
|
const QString FullscreenMirror = "Mirror";
|
||||||
const QString Help = "Help...";
|
const QString Help = "Help...";
|
||||||
|
const QString IncrementalTextureTransfer = "Enable Incremental Texture Transfer";
|
||||||
const QString IncreaseAvatarSize = "Increase Avatar Size";
|
const QString IncreaseAvatarSize = "Increase Avatar Size";
|
||||||
const QString IndependentMode = "Independent Mode";
|
const QString IndependentMode = "Independent Mode";
|
||||||
const QString ActionMotorControl = "Enable Default Motor Control";
|
const QString ActionMotorControl = "Enable Default Motor Control";
|
||||||
|
@ -180,6 +179,7 @@ namespace MenuOption {
|
||||||
const QString StandingHMDSensorMode = "Standing HMD Sensor Mode";
|
const QString StandingHMDSensorMode = "Standing HMD Sensor Mode";
|
||||||
const QString SimulateEyeTracking = "Simulate";
|
const QString SimulateEyeTracking = "Simulate";
|
||||||
const QString SMIEyeTracking = "SMI Eye Tracking";
|
const QString SMIEyeTracking = "SMI Eye Tracking";
|
||||||
|
const QString SparseTextureManagement = "Enable Sparse Texture Management";
|
||||||
const QString Stats = "Stats";
|
const QString Stats = "Stats";
|
||||||
const QString StopAllScripts = "Stop All Scripts";
|
const QString StopAllScripts = "Stop All Scripts";
|
||||||
const QString SuppressShortTimings = "Suppress Timings Less than 10ms";
|
const QString SuppressShortTimings = "Suppress Timings Less than 10ms";
|
||||||
|
|
|
@ -177,7 +177,6 @@ public:
|
||||||
virtual void queueLambda(const std::function<void()> lambda) const;
|
virtual void queueLambda(const std::function<void()> lambda) const;
|
||||||
|
|
||||||
bool isTextureManagementSparseEnabled() const override { return (_textureManagement._sparseCapable && Texture::getEnableSparseTextures()); }
|
bool isTextureManagementSparseEnabled() const override { return (_textureManagement._sparseCapable && Texture::getEnableSparseTextures()); }
|
||||||
bool isTextureManagementIncrementalTransferEnabled() const override { return (_textureManagement._incrementalTransferCapable && Texture::getEnableIncrementalTextureTransfers()); }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -369,7 +368,6 @@ protected:
|
||||||
|
|
||||||
struct TextureManagementStageState {
|
struct TextureManagementStageState {
|
||||||
bool _sparseCapable { false };
|
bool _sparseCapable { false };
|
||||||
bool _incrementalTransferCapable { false };
|
|
||||||
} _textureManagement;
|
} _textureManagement;
|
||||||
virtual void initTextureManagementStage() {}
|
virtual void initTextureManagementStage() {}
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,7 @@ float GLTexture::getMemoryPressure() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the consumed texture memory divided by the available texture memory.
|
// Return the consumed texture memory divided by the available texture memory.
|
||||||
auto consumedGpuMemory = Context::getTextureGPUSparseMemoryUsage();
|
auto consumedGpuMemory = Context::getTextureGPUMemoryUsage() - Context::getTextureGPUFramebufferMemoryUsage();
|
||||||
float memoryPressure = (float)consumedGpuMemory / (float)availableTextureMemory;
|
float memoryPressure = (float)consumedGpuMemory / (float)availableTextureMemory;
|
||||||
static Context::Size lastConsumedGpuMemory = 0;
|
static Context::Size lastConsumedGpuMemory = 0;
|
||||||
if (memoryPressure > 1.0f && lastConsumedGpuMemory != consumedGpuMemory) {
|
if (memoryPressure > 1.0f && lastConsumedGpuMemory != consumedGpuMemory) {
|
||||||
|
|
|
@ -94,6 +94,7 @@ public:
|
||||||
TransferState _transferState;
|
TransferState _transferState;
|
||||||
uint32_t _allocatedPages { 0 };
|
uint32_t _allocatedPages { 0 };
|
||||||
uint32_t _lastMipAllocatedPages { 0 };
|
uint32_t _lastMipAllocatedPages { 0 };
|
||||||
|
uint16_t _mipOffset { 0 };
|
||||||
friend class GL45Backend;
|
friend class GL45Backend;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -148,13 +148,9 @@ uint32_t SparseInfo::getPageCount(const uvec3& dimensions) const {
|
||||||
return pageCounts.x * pageCounts.y * pageCounts.z;
|
return pageCounts.x * pageCounts.y * pageCounts.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void GL45Backend::initTextureManagementStage() {
|
void GL45Backend::initTextureManagementStage() {
|
||||||
|
|
||||||
// enable the Sparse Texture on gl45
|
// enable the Sparse Texture on gl45
|
||||||
_textureManagement._sparseCapable = true;
|
_textureManagement._sparseCapable = true;
|
||||||
_textureManagement._incrementalTransferCapable = true;
|
|
||||||
|
|
||||||
// But now let s refine the behavior based on vendor
|
// But now let s refine the behavior based on vendor
|
||||||
std::string vendor { (const char*)glGetString(GL_VENDOR) };
|
std::string vendor { (const char*)glGetString(GL_VENDOR) };
|
||||||
|
@ -282,20 +278,22 @@ GL45Texture::~GL45Texture() {
|
||||||
if (!_gpuObject.getUsage().isExternal()) {
|
if (!_gpuObject.getUsage().isExternal()) {
|
||||||
qCDebug(gpugl45logging) << "Destroying texture " << _id << " from source " << _source.c_str();
|
qCDebug(gpugl45logging) << "Destroying texture " << _id << " from source " << _source.c_str();
|
||||||
}
|
}
|
||||||
if (_sparseInfo.sparse) {
|
|
||||||
Backend::decrementTextureGPUSparseCount();
|
// Remove this texture from the candidate list of derezzable textures
|
||||||
// Remove this texture from the candidate list of derezzable textures
|
if (_transferrable) {
|
||||||
{
|
auto mipLevels = usedMipLevels();
|
||||||
auto mipLevels = usedMipLevels();
|
Lock lock(texturesByMipCountsMutex);
|
||||||
Lock lock(texturesByMipCountsMutex);
|
if (texturesByMipCounts.count(mipLevels)) {
|
||||||
if (texturesByMipCounts.count(mipLevels)) {
|
auto& textures = texturesByMipCounts[mipLevels];
|
||||||
auto& textures = texturesByMipCounts[mipLevels];
|
textures.erase(this);
|
||||||
textures.erase(this);
|
if (textures.empty()) {
|
||||||
if (textures.empty()) {
|
texturesByMipCounts.erase(mipLevels);
|
||||||
texturesByMipCounts.erase(mipLevels);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_sparseInfo.sparse) {
|
||||||
|
Backend::decrementTextureGPUSparseCount();
|
||||||
|
|
||||||
// Experimenation suggests that allocating sparse textures on one context/thread and deallocating
|
// Experimenation suggests that allocating sparse textures on one context/thread and deallocating
|
||||||
// them on another is buggy. So for sparse textures we need to queue a lambda with the deallocation
|
// them on another is buggy. So for sparse textures we need to queue a lambda with the deallocation
|
||||||
|
@ -355,7 +353,7 @@ void GL45Texture::allocateStorage() const {
|
||||||
glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, 0);
|
glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
glTextureParameteri(_id, GL_TEXTURE_MAX_LEVEL, _maxMip - _minMip);
|
glTextureParameteri(_id, GL_TEXTURE_MAX_LEVEL, _maxMip - _minMip);
|
||||||
// Get the dimensions, accounting for the downgrade level
|
// Get the dimensions, accounting for the downgrade level
|
||||||
Vec3u dimensions = _gpuObject.evalMipDimensions(_minMip);
|
Vec3u dimensions = _gpuObject.evalMipDimensions(_minMip + _mipOffset);
|
||||||
glTextureStorage2D(_id, usedMipLevels(), _internalFormat, dimensions.x, dimensions.y);
|
glTextureStorage2D(_id, usedMipLevels(), _internalFormat, dimensions.x, dimensions.y);
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
@ -370,7 +368,7 @@ void GL45Texture::updateSize() const {
|
||||||
Backend::updateTextureGPUSparseMemoryUsage(_size, size);
|
Backend::updateTextureGPUSparseMemoryUsage(_size, size);
|
||||||
setSize(_allocatedPages * _sparseInfo.pageBytes);
|
setSize(_allocatedPages * _sparseInfo.pageBytes);
|
||||||
} else {
|
} else {
|
||||||
setSize(_virtualSize);
|
setSize(_gpuObject.evalTotalSize(_mipOffset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,15 +379,18 @@ void GL45Texture::startTransfer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GL45Texture::continueTransfer() {
|
bool GL45Texture::continueTransfer() {
|
||||||
auto backend = _backend.lock();
|
if (!Texture::getEnableIncrementalTextureTransfers()) {
|
||||||
if (!backend || !backend->isTextureManagementIncrementalTransferEnabled()) {
|
|
||||||
size_t maxFace = GL_TEXTURE_CUBE_MAP == _target ? CUBE_NUM_FACES : 1;
|
size_t maxFace = GL_TEXTURE_CUBE_MAP == _target ? CUBE_NUM_FACES : 1;
|
||||||
for (uint8_t face = 0; face < maxFace; ++face) {
|
for (uint8_t face = 0; face < maxFace; ++face) {
|
||||||
for (uint16_t mipLevel = _minMip; mipLevel <= _maxMip; ++mipLevel) {
|
for (uint16_t mipLevel = _minMip; mipLevel <= _maxMip; ++mipLevel) {
|
||||||
|
auto size = _gpuObject.evalMipDimensions(mipLevel);
|
||||||
|
if (_sparseInfo.sparse && mipLevel <= _sparseInfo.maxSparseLevel) {
|
||||||
|
glTexturePageCommitmentEXT(_id, mipLevel, 0, 0, face, size.x, size.y, 1, GL_TRUE);
|
||||||
|
_allocatedPages += _sparseInfo.getPageCount(size);
|
||||||
|
}
|
||||||
if (_gpuObject.isStoredMipFaceAvailable(mipLevel, face)) {
|
if (_gpuObject.isStoredMipFaceAvailable(mipLevel, face)) {
|
||||||
auto mip = _gpuObject.accessStoredMipFace(mipLevel, face);
|
auto mip = _gpuObject.accessStoredMipFace(mipLevel, face);
|
||||||
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), mip->getFormat());
|
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), mip->getFormat());
|
||||||
auto size = _gpuObject.evalMipDimensions(mipLevel);
|
|
||||||
if (GL_TEXTURE_2D == _target) {
|
if (GL_TEXTURE_2D == _target) {
|
||||||
glTextureSubImage2D(_id, mipLevel, 0, 0, size.x, size.y, texelFormat.format, texelFormat.type, mip->readData());
|
glTextureSubImage2D(_id, mipLevel, 0, 0, size.x, size.y, texelFormat.format, texelFormat.type, mip->readData());
|
||||||
} else if (GL_TEXTURE_CUBE_MAP == _target) {
|
} else if (GL_TEXTURE_CUBE_MAP == _target) {
|
||||||
|
@ -481,35 +482,30 @@ void GL45Texture::syncSampler() const {
|
||||||
glTextureParameteri(_id, GL_TEXTURE_WRAP_T, WRAP_MODES[sampler.getWrapModeV()]);
|
glTextureParameteri(_id, GL_TEXTURE_WRAP_T, WRAP_MODES[sampler.getWrapModeV()]);
|
||||||
glTextureParameteri(_id, GL_TEXTURE_WRAP_R, WRAP_MODES[sampler.getWrapModeW()]);
|
glTextureParameteri(_id, GL_TEXTURE_WRAP_R, WRAP_MODES[sampler.getWrapModeW()]);
|
||||||
glTextureParameterfv(_id, GL_TEXTURE_BORDER_COLOR, (const float*)&sampler.getBorderColor());
|
glTextureParameterfv(_id, GL_TEXTURE_BORDER_COLOR, (const float*)&sampler.getBorderColor());
|
||||||
|
// FIXME account for mip offsets here
|
||||||
auto baseMip = std::max<uint16_t>(sampler.getMipOffset(), _minMip);
|
auto baseMip = std::max<uint16_t>(sampler.getMipOffset(), _minMip);
|
||||||
glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, baseMip);
|
glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, baseMip);
|
||||||
glTextureParameterf(_id, GL_TEXTURE_MIN_LOD, (float)sampler.getMinMip());
|
glTextureParameterf(_id, GL_TEXTURE_MIN_LOD, (float)sampler.getMinMip());
|
||||||
glTextureParameterf(_id, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip()));
|
glTextureParameterf(_id, GL_TEXTURE_MAX_LOD, (sampler.getMaxMip() == Sampler::MAX_MIP_LEVEL ? 1000.f : sampler.getMaxMip() - _mipOffset));
|
||||||
glTextureParameterf(_id, GL_TEXTURE_MAX_ANISOTROPY_EXT, sampler.getMaxAnisotropy());
|
glTextureParameterf(_id, GL_TEXTURE_MAX_ANISOTROPY_EXT, sampler.getMaxAnisotropy());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GL45Texture::postTransfer() {
|
void GL45Texture::postTransfer() {
|
||||||
Parent::postTransfer();
|
Parent::postTransfer();
|
||||||
if (_sparseInfo.sparse) {
|
auto mipLevels = usedMipLevels();
|
||||||
auto mipLevels = usedMipLevels();
|
if (_transferrable && mipLevels > 1 && _minMip < _sparseInfo.maxSparseLevel) {
|
||||||
if (mipLevels > 1 && _minMip < _sparseInfo.maxSparseLevel) {
|
Lock lock(texturesByMipCountsMutex);
|
||||||
Lock lock(texturesByMipCountsMutex);
|
texturesByMipCounts[mipLevels].insert(this);
|
||||||
texturesByMipCounts[mipLevels].insert(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GL45Texture::stripToMip(uint16_t newMinMip) {
|
void GL45Texture::stripToMip(uint16_t newMinMip) {
|
||||||
if (!_sparseInfo.sparse) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newMinMip < _minMip) {
|
if (newMinMip < _minMip) {
|
||||||
qCWarning(gpugl45logging) << "Cannot decrease the min mip";
|
qCWarning(gpugl45logging) << "Cannot decrease the min mip";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newMinMip > _sparseInfo.maxSparseLevel) {
|
if (_sparseInfo.sparse && newMinMip > _sparseInfo.maxSparseLevel) {
|
||||||
qCWarning(gpugl45logging) << "Cannot increase the min mip into the mip tail";
|
qCWarning(gpugl45logging) << "Cannot increase the min mip into the mip tail";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -533,19 +529,53 @@ void GL45Texture::stripToMip(uint16_t newMinMip) {
|
||||||
|
|
||||||
|
|
||||||
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 mip = _minMip; mip < newMinMip; ++mip) {
|
if (_sparseInfo.sparse) {
|
||||||
auto id = _id;
|
for (uint16_t mip = _minMip; mip < newMinMip; ++mip) {
|
||||||
auto mipDimensions = _gpuObject.evalMipDimensions(mip);
|
auto id = _id;
|
||||||
_textureTransferHelper->queueExecution([id, mip, mipDimensions, maxFace] {
|
auto mipDimensions = _gpuObject.evalMipDimensions(mip);
|
||||||
glTexturePageCommitmentEXT(id, mip, 0, 0, 0, mipDimensions.x, mipDimensions.y, maxFace, GL_FALSE);
|
_textureTransferHelper->queueExecution([id, mip, mipDimensions, maxFace] {
|
||||||
});
|
glTexturePageCommitmentEXT(id, mip, 0, 0, 0, mipDimensions.x, mipDimensions.y, maxFace, GL_FALSE);
|
||||||
|
});
|
||||||
|
|
||||||
auto deallocatedPages = _sparseInfo.getPageCount(mipDimensions) * maxFace;
|
auto deallocatedPages = _sparseInfo.getPageCount(mipDimensions) * maxFace;
|
||||||
assert(deallocatedPages < _allocatedPages);
|
assert(deallocatedPages < _allocatedPages);
|
||||||
_allocatedPages -= deallocatedPages;
|
_allocatedPages -= deallocatedPages;
|
||||||
|
}
|
||||||
|
_minMip = newMinMip;
|
||||||
|
} else {
|
||||||
|
GLuint oldId = _id;
|
||||||
|
// Find the distance between the old min mip and the new one
|
||||||
|
uint16 mipDelta = newMinMip - _minMip;
|
||||||
|
_mipOffset += mipDelta;
|
||||||
|
const_cast<uint16&>(_maxMip) -= mipDelta;
|
||||||
|
auto newLevels = usedMipLevels();
|
||||||
|
|
||||||
|
// Create and setup the new texture (allocate)
|
||||||
|
glCreateTextures(_target, 1, &const_cast<GLuint&>(_id));
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
|
glTextureParameteri(_id, GL_TEXTURE_MAX_LEVEL, _maxMip - _minMip);
|
||||||
|
Vec3u newDimensions = _gpuObject.evalMipDimensions(_mipOffset);
|
||||||
|
glTextureStorage2D(_id, newLevels, _internalFormat, newDimensions.x, newDimensions.y);
|
||||||
|
|
||||||
|
// Copy the contents of the old texture to the new
|
||||||
|
GLuint fbo { 0 };
|
||||||
|
glCreateFramebuffers(1, &fbo);
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
|
||||||
|
for (uint16 targetMip = _minMip; targetMip <= _maxMip; ++targetMip) {
|
||||||
|
uint16 sourceMip = targetMip + mipDelta;
|
||||||
|
Vec3u mipDimensions = _gpuObject.evalMipDimensions(targetMip + _mipOffset);
|
||||||
|
for (GLenum target : getFaceTargets(_target)) {
|
||||||
|
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, oldId, sourceMip);
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
glCopyTextureSubImage2D(_id, targetMip, 0, 0, 0, 0, mipDimensions.x, mipDimensions.y);
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||||
|
glDeleteFramebuffers(1, &fbo);
|
||||||
|
glDeleteTextures(1, &oldId);
|
||||||
}
|
}
|
||||||
|
|
||||||
_minMip = newMinMip;
|
|
||||||
// Re-sync the sampler to force access to the new mip level
|
// Re-sync the sampler to force access to the new mip level
|
||||||
syncSampler();
|
syncSampler();
|
||||||
updateSize();
|
updateSize();
|
||||||
|
@ -553,7 +583,7 @@ void GL45Texture::stripToMip(uint16_t newMinMip) {
|
||||||
|
|
||||||
// Re-insert into the texture-by-mips map if appropriate
|
// Re-insert into the texture-by-mips map if appropriate
|
||||||
mipLevels = usedMipLevels();
|
mipLevels = usedMipLevels();
|
||||||
if (_sparseInfo.sparse && mipLevels > 1 && _minMip < _sparseInfo.maxSparseLevel) {
|
if (mipLevels > 1 && (!_sparseInfo.sparse || _minMip < _sparseInfo.maxSparseLevel)) {
|
||||||
Lock lock(texturesByMipCountsMutex);
|
Lock lock(texturesByMipCountsMutex);
|
||||||
texturesByMipCounts[mipLevels].insert(this);
|
texturesByMipCounts[mipLevels].insert(this);
|
||||||
}
|
}
|
||||||
|
@ -570,8 +600,9 @@ void GL45Texture::updateMips() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GL45Texture::derez() {
|
void GL45Texture::derez() {
|
||||||
assert(_sparseInfo.sparse);
|
if (_sparseInfo.sparse) {
|
||||||
assert(_minMip < _sparseInfo.maxSparseLevel);
|
assert(_minMip < _sparseInfo.maxSparseLevel);
|
||||||
|
}
|
||||||
assert(_minMip < _maxMip);
|
assert(_minMip < _maxMip);
|
||||||
assert(_transferrable);
|
assert(_transferrable);
|
||||||
stripToMip(_minMip + 1);
|
stripToMip(_minMip + 1);
|
||||||
|
@ -595,7 +626,7 @@ void GL45Backend::derezTextures() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(gpugl45logging) << "Allowed texture memory " << Texture::getAllowedGPUMemoryUsage();
|
qCDebug(gpugl45logging) << "Allowed texture memory " << Texture::getAllowedGPUMemoryUsage();
|
||||||
qCDebug(gpugl45logging) << "Used texture memory " << Context::getTextureGPUMemoryUsage();
|
qCDebug(gpugl45logging) << "Used texture memory " << (Context::getTextureGPUMemoryUsage() - Context::getTextureGPUFramebufferMemoryUsage());
|
||||||
|
|
||||||
GL45Texture* targetTexture = nullptr;
|
GL45Texture* targetTexture = nullptr;
|
||||||
{
|
{
|
||||||
|
@ -605,5 +636,5 @@ void GL45Backend::derezTextures() const {
|
||||||
}
|
}
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
targetTexture->derez();
|
targetTexture->derez();
|
||||||
qCDebug(gpugl45logging) << "New Used texture memory " << Context::getTextureGPUMemoryUsage();
|
qCDebug(gpugl45logging) << "New Used texture memory " << (Context::getTextureGPUMemoryUsage() - Context::getTextureGPUFramebufferMemoryUsage());
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,6 @@ public:
|
||||||
void getStats(ContextStats& stats) const { stats = _stats; }
|
void getStats(ContextStats& stats) const { stats = _stats; }
|
||||||
|
|
||||||
virtual bool isTextureManagementSparseEnabled() const = 0;
|
virtual bool isTextureManagementSparseEnabled() const = 0;
|
||||||
virtual bool isTextureManagementIncrementalTransferEnabled() const = 0;
|
|
||||||
|
|
||||||
// These should only be accessed by Backend implementation to repport the buffer and texture allocations,
|
// These should only be accessed by Backend implementation to repport the buffer and texture allocations,
|
||||||
// they are NOT public calls
|
// they are NOT public calls
|
||||||
|
|
|
@ -10,11 +10,13 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
|
||||||
|
|
||||||
#include "Texture.h"
|
#include "Texture.h"
|
||||||
|
|
||||||
#include <glm/gtc/constants.hpp>
|
#include <glm/gtc/constants.hpp>
|
||||||
|
#include <glm/gtx/component_wise.hpp>
|
||||||
|
|
||||||
|
#include <QtCore/QDebug>
|
||||||
|
#include <QtCore/QThread>
|
||||||
|
|
||||||
#include <NumericalConstants.h>
|
#include <NumericalConstants.h>
|
||||||
|
|
||||||
|
@ -31,16 +33,27 @@ std::atomic<uint32_t> Texture::_textureCPUCount{ 0 };
|
||||||
std::atomic<Texture::Size> Texture::_textureCPUMemoryUsage{ 0 };
|
std::atomic<Texture::Size> Texture::_textureCPUMemoryUsage{ 0 };
|
||||||
std::atomic<Texture::Size> Texture::_allowedCPUMemoryUsage { 0 };
|
std::atomic<Texture::Size> Texture::_allowedCPUMemoryUsage { 0 };
|
||||||
|
|
||||||
std::atomic<bool> Texture::_enableSparseTextures { false };
|
|
||||||
std::atomic<bool> Texture::_enableIncrementalTextureTransfers { false };
|
#define MIN_CORES_FOR_INCREMENTAL_TEXTURES 5
|
||||||
|
bool recommendedIncrementalTransfers = (QThread::idealThreadCount() >= MIN_CORES_FOR_INCREMENTAL_TEXTURES);
|
||||||
|
bool recommendedSparseTextures = recommendedIncrementalTransfers;
|
||||||
|
|
||||||
|
std::atomic<bool> Texture::_enableSparseTextures { recommendedIncrementalTransfers };
|
||||||
|
std::atomic<bool> Texture::_enableIncrementalTextureTransfers { recommendedSparseTextures };
|
||||||
|
|
||||||
|
struct ReportTextureState {
|
||||||
|
ReportTextureState() {
|
||||||
|
qDebug() << "[TEXTURE TRANSFER SUPPORT]"
|
||||||
|
<< "\n\tidealThreadCount:" << QThread::idealThreadCount()
|
||||||
|
<< "\n\tRECOMMENDED enableSparseTextures:" << recommendedSparseTextures
|
||||||
|
<< "\n\tRECOMMENDED enableIncrementalTextures:" << recommendedIncrementalTransfers;
|
||||||
|
}
|
||||||
|
} report;
|
||||||
|
|
||||||
void Texture::setEnableSparseTextures(bool enabled) {
|
void Texture::setEnableSparseTextures(bool enabled) {
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
qDebug() << "[TEXTURE TRANSFER SUPPORT] SETTING - Enable Sparse Textures and Dynamic Texture Management:" << enabled;
|
qDebug() << "[TEXTURE TRANSFER SUPPORT] SETTING - Enable Sparse Textures and Dynamic Texture Management:" << enabled;
|
||||||
_enableSparseTextures = enabled;
|
_enableSparseTextures = enabled;
|
||||||
if (!_enableIncrementalTextureTransfers && _enableSparseTextures) {
|
|
||||||
qDebug() << "[TEXTURE TRANSFER SUPPORT] WARNING - Sparse texture management requires incremental texture transfer enabled.";
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
qDebug() << "[TEXTURE TRANSFER SUPPORT] Sparse Textures and Dynamic Texture Management not supported on this platform.";
|
qDebug() << "[TEXTURE TRANSFER SUPPORT] Sparse Textures and Dynamic Texture Management not supported on this platform.";
|
||||||
#endif
|
#endif
|
||||||
|
@ -50,9 +63,6 @@ void Texture::setEnableIncrementalTextureTransfers(bool enabled) {
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
qDebug() << "[TEXTURE TRANSFER SUPPORT] SETTING - Enable Incremental Texture Transfer:" << enabled;
|
qDebug() << "[TEXTURE TRANSFER SUPPORT] SETTING - Enable Incremental Texture Transfer:" << enabled;
|
||||||
_enableIncrementalTextureTransfers = enabled;
|
_enableIncrementalTextureTransfers = enabled;
|
||||||
if (!_enableIncrementalTextureTransfers && _enableSparseTextures) {
|
|
||||||
qDebug() << "[TEXTURE TRANSFER SUPPORT] WARNING - Sparse texture management requires incremental texture transfer enabled.";
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
qDebug() << "[TEXTURE TRANSFER SUPPORT] Incremental Texture Transfer not supported on this platform.";
|
qDebug() << "[TEXTURE TRANSFER SUPPORT] Incremental Texture Transfer not supported on this platform.";
|
||||||
#endif
|
#endif
|
||||||
|
@ -418,12 +428,18 @@ uint16 Texture::evalDimNumMips(uint16 size) {
|
||||||
return 1 + (uint16) val;
|
return 1 + (uint16) val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const double LOG_2 = log(2.0);
|
||||||
|
|
||||||
|
uint16 Texture::evalNumMips(const Vec3u& dimensions) {
|
||||||
|
double largerDim = glm::compMax(dimensions);
|
||||||
|
double val = log(largerDim) / LOG_2;
|
||||||
|
return 1 + (uint16)val;
|
||||||
|
}
|
||||||
|
|
||||||
// The number mips that the texture could have if all existed
|
// The number mips that the texture could have if all existed
|
||||||
// = log2(max(width, height, depth))
|
// = log2(max(width, height, depth))
|
||||||
uint16 Texture::evalNumMips() const {
|
uint16 Texture::evalNumMips() const {
|
||||||
double largerDim = std::max(std::max(_width, _height), _depth);
|
return evalNumMips({ _width, _height, _depth });
|
||||||
double val = log(largerDim)/log(2.0);
|
|
||||||
return 1 + (uint16) val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Texture::assignStoredMip(uint16 level, const Element& format, Size size, const Byte* bytes) {
|
bool Texture::assignStoredMip(uint16 level, const Element& format, Size size, const Byte* bytes) {
|
||||||
|
|
|
@ -369,9 +369,12 @@ public:
|
||||||
// = 1 + log2(max(width, height, depth))
|
// = 1 + log2(max(width, height, depth))
|
||||||
uint16 evalNumMips() const;
|
uint16 evalNumMips() const;
|
||||||
|
|
||||||
|
static uint16 evalNumMips(const Vec3u& dimensions);
|
||||||
|
|
||||||
// Eval the size that the mips level SHOULD have
|
// Eval the size that the mips level SHOULD have
|
||||||
// not the one stored in the Texture
|
// not the one stored in the Texture
|
||||||
static const uint MIN_DIMENSION = 1;
|
static const uint MIN_DIMENSION = 1;
|
||||||
|
|
||||||
Vec3u evalMipDimensions(uint16 level) const;
|
Vec3u evalMipDimensions(uint16 level) const;
|
||||||
uint16 evalMipWidth(uint16 level) const { return std::max(_width >> level, 1); }
|
uint16 evalMipWidth(uint16 level) const { return std::max(_width >> level, 1); }
|
||||||
uint16 evalMipHeight(uint16 level) const { return std::max(_height >> level, 1); }
|
uint16 evalMipHeight(uint16 level) const { return std::max(_height >> level, 1); }
|
||||||
|
@ -388,9 +391,9 @@ public:
|
||||||
uint32 evalStoredMipFaceSize(uint16 level, const Element& format) const { return evalMipFaceNumTexels(level) * format.getSize(); }
|
uint32 evalStoredMipFaceSize(uint16 level, const Element& format) const { return evalMipFaceNumTexels(level) * format.getSize(); }
|
||||||
uint32 evalStoredMipSize(uint16 level, const Element& format) const { return evalMipNumTexels(level) * format.getSize(); }
|
uint32 evalStoredMipSize(uint16 level, const Element& format) const { return evalMipNumTexels(level) * format.getSize(); }
|
||||||
|
|
||||||
uint32 evalTotalSize() const {
|
uint32 evalTotalSize(uint16 startingMip = 0) const {
|
||||||
uint32 size = 0;
|
uint32 size = 0;
|
||||||
uint16 minMipLevel = minMip();
|
uint16 minMipLevel = std::max(minMip(), startingMip);
|
||||||
uint16 maxMipLevel = maxMip();
|
uint16 maxMipLevel = maxMip();
|
||||||
for (uint16 l = minMipLevel; l <= maxMipLevel; l++) {
|
for (uint16 l = minMipLevel; l <= maxMipLevel; l++) {
|
||||||
size += evalMipSize(l);
|
size += evalMipSize(l);
|
||||||
|
|
|
@ -599,7 +599,7 @@ protected:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case Qt::Key_End:
|
case Qt::Key_End:
|
||||||
gpu::Texture::setAllowedGPUMemoryUsage(MB_TO_BYTES(256));
|
gpu::Texture::setAllowedGPUMemoryUsage(MB_TO_BYTES(64));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue