mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-08 06:32:35 +02:00
Merge pull request #9803 from jherico/smarter_textures
Throttle texture creation
This commit is contained in:
commit
9ae750b749
17 changed files with 93 additions and 39 deletions
|
@ -207,7 +207,7 @@ void GLBackend::renderPassTransfer(const Batch& batch) {
|
|||
}
|
||||
}
|
||||
|
||||
{ // Sync all the buffers
|
||||
{ // Sync all the transform states
|
||||
PROFILE_RANGE(render_gpu_gl_detail, "syncCPUTransform");
|
||||
_transform._cameras.clear();
|
||||
_transform._cameraOffsets.clear();
|
||||
|
@ -275,7 +275,7 @@ void GLBackend::renderPassDraw(const Batch& batch) {
|
|||
updateInput();
|
||||
updateTransform(batch);
|
||||
updatePipeline();
|
||||
|
||||
|
||||
CommandCall call = _commandCalls[(*command)];
|
||||
(this->*(call))(batch, *offset);
|
||||
break;
|
||||
|
|
|
@ -72,7 +72,6 @@ GL41Texture::GL41Texture(const std::weak_ptr<GLBackend>& backend, const Texture&
|
|||
incrementTextureGPUCount();
|
||||
withPreservedTexture([&] {
|
||||
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat(), _gpuObject.getStoredMipFormat());
|
||||
const Sampler& sampler = _gpuObject.getSampler();
|
||||
auto numMips = _gpuObject.evalNumMips();
|
||||
for (uint16_t mipLevel = 0; mipLevel < numMips; ++mipLevel) {
|
||||
// Get the mip level dimensions, accounting for the downgrade level
|
||||
|
|
|
@ -18,6 +18,12 @@ Q_LOGGING_CATEGORY(gpugl45logging, "hifi.gpu.gl45")
|
|||
using namespace gpu;
|
||||
using namespace gpu::gl45;
|
||||
|
||||
void GL45Backend::recycle() const {
|
||||
Parent::recycle();
|
||||
GL45VariableAllocationTexture::manageMemory();
|
||||
GL45VariableAllocationTexture::_frameTexturesCreated = 0;
|
||||
}
|
||||
|
||||
void GL45Backend::do_draw(const Batch& batch, size_t paramOffset) {
|
||||
Primitive primitiveType = (Primitive)batch._params[paramOffset + 2]._uint;
|
||||
GLenum mode = gl::PRIMITIVE_TO_GL[primitiveType];
|
||||
|
|
|
@ -147,6 +147,7 @@ public:
|
|||
using TransferQueue = std::queue<std::unique_ptr<TransferJob>>;
|
||||
static MemoryPressureState _memoryPressureState;
|
||||
protected:
|
||||
static size_t _frameTexturesCreated;
|
||||
static std::atomic<bool> _memoryPressureStateStale;
|
||||
static std::list<TextureWeakPointer> _memoryManagedTextures;
|
||||
static WorkQueue _transferQueue;
|
||||
|
|
|
@ -28,6 +28,7 @@ using namespace gpu::gl;
|
|||
using namespace gpu::gl45;
|
||||
|
||||
#define SPARSE_PAGE_SIZE_OVERHEAD_ESTIMATE 1.3f
|
||||
#define MAX_RESOURCE_TEXTURES_PER_FRAME 2
|
||||
|
||||
GLTexture* GL45Backend::syncGPUObject(const TexturePointer& texturePointer) {
|
||||
if (!texturePointer) {
|
||||
|
@ -57,19 +58,23 @@ GLTexture* GL45Backend::syncGPUObject(const TexturePointer& texturePointer) {
|
|||
break;
|
||||
|
||||
case TextureUsageType::RESOURCE: {
|
||||
|
||||
GL45VariableAllocationTexture* varObject { nullptr };
|
||||
if (GL45VariableAllocationTexture::_frameTexturesCreated < MAX_RESOURCE_TEXTURES_PER_FRAME) {
|
||||
#if 0
|
||||
if (isTextureManagementSparseEnabled() && GL45Texture::isSparseEligible(texture)) {
|
||||
varObject = new GL45SparseResourceTexture(shared_from_this(), texture);
|
||||
} else {
|
||||
varObject = new GL45ResourceTexture(shared_from_this(), texture);
|
||||
}
|
||||
if (isTextureManagementSparseEnabled() && GL45Texture::isSparseEligible(texture)) {
|
||||
object = new GL45SparseResourceTexture(shared_from_this(), texture);
|
||||
} else {
|
||||
object = new GL45ResourceTexture(shared_from_this(), texture);
|
||||
}
|
||||
#else
|
||||
varObject = new GL45ResourceTexture(shared_from_this(), texture);
|
||||
object = new GL45ResourceTexture(shared_from_this(), texture);
|
||||
#endif
|
||||
GL45VariableAllocationTexture::addMemoryManagedTexture(texturePointer);
|
||||
object = varObject;
|
||||
GL45VariableAllocationTexture::addMemoryManagedTexture(texturePointer);
|
||||
} else {
|
||||
auto fallback = texturePointer->getFallbackTexture();
|
||||
if (fallback) {
|
||||
object = static_cast<GL45Texture*>(syncGPUObject(fallback));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -81,11 +86,6 @@ GLTexture* GL45Backend::syncGPUObject(const TexturePointer& texturePointer) {
|
|||
return object;
|
||||
}
|
||||
|
||||
void GL45Backend::recycle() const {
|
||||
Parent::recycle();
|
||||
GL45VariableAllocationTexture::manageMemory();
|
||||
}
|
||||
|
||||
void GL45Backend::initTextureManagementStage() {
|
||||
// enable the Sparse Texture on gl45
|
||||
_textureManagement._sparseCapable = true;
|
||||
|
|
|
@ -405,7 +405,10 @@ void GL45VariableAllocationTexture::manageMemory() {
|
|||
processWorkQueues();
|
||||
}
|
||||
|
||||
size_t GL45VariableAllocationTexture::_frameTexturesCreated { 0 };
|
||||
|
||||
GL45VariableAllocationTexture::GL45VariableAllocationTexture(const std::weak_ptr<GLBackend>& backend, const Texture& texture) : GL45Texture(backend, texture) {
|
||||
++_frameTexturesCreated;
|
||||
}
|
||||
|
||||
GL45VariableAllocationTexture::~GL45VariableAllocationTexture() {
|
||||
|
|
|
@ -412,7 +412,6 @@ void Texture::assignStoredMip(uint16 level, storage::StoragePointer& storage) {
|
|||
// THen check that the mem texture passed make sense with its format
|
||||
Size expectedSize = evalStoredMipSize(level, getStoredMipFormat());
|
||||
auto size = storage->size();
|
||||
auto bytes = storage->data();
|
||||
if (storage->size() == expectedSize) {
|
||||
_storage->assignMipData(level, storage);
|
||||
_maxMip = std::max(_maxMip, level);
|
||||
|
@ -442,7 +441,6 @@ void Texture::assignStoredMipFace(uint16 level, uint8 face, storage::StoragePoin
|
|||
// THen check that the mem texture passed make sense with its format
|
||||
Size expectedSize = evalStoredMipFaceSize(level, getStoredMipFormat());
|
||||
auto size = storage->size();
|
||||
auto bytes = storage->data();
|
||||
if (size == expectedSize) {
|
||||
_storage->assignMipFaceData(level, face, storage);
|
||||
_maxMip = std::max(_maxMip, level);
|
||||
|
|
|
@ -503,6 +503,9 @@ public:
|
|||
const Sampler& getSampler() const { return _sampler; }
|
||||
Stamp getSamplerStamp() const { return _samplerStamp; }
|
||||
|
||||
void setFallbackTexture(const TexturePointer& fallback) { _fallback = fallback; }
|
||||
TexturePointer getFallbackTexture() const { return _fallback.lock(); }
|
||||
|
||||
void setExternalTexture(uint32 externalId, void* externalFence);
|
||||
void setExternalRecycler(const ExternalRecycler& recycler);
|
||||
ExternalRecycler getExternalRecycler() const;
|
||||
|
@ -526,6 +529,7 @@ protected:
|
|||
ExternalRecycler _externalRecycler;
|
||||
|
||||
|
||||
std::weak_ptr<Texture> _fallback;
|
||||
// Not strictly necessary, but incredibly useful for debugging
|
||||
std::string _source;
|
||||
std::unique_ptr< Storage > _storage;
|
||||
|
|
|
@ -117,6 +117,7 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) {
|
|||
}
|
||||
|
||||
auto ktxBuffer = ktx::KTX::create(header, images);
|
||||
#if 0
|
||||
auto expectedMipCount = texture.evalNumMips();
|
||||
assert(expectedMipCount == ktxBuffer->_images.size());
|
||||
assert(expectedMipCount == header.numberOfMipmapLevels);
|
||||
|
@ -141,6 +142,7 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) {
|
|||
assert(0 == memcmp(expectedFace, actualFace, expected._faceSize));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return ktxBuffer;
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ KTX::KTX() {
|
|||
KTX::~KTX() {
|
||||
}
|
||||
|
||||
void KTX::resetStorage(StoragePointer& storage) {
|
||||
void KTX::resetStorage(const StoragePointer& storage) {
|
||||
_storage = storage;
|
||||
}
|
||||
|
||||
|
|
|
@ -402,15 +402,15 @@ namespace ktx {
|
|||
Image(uint32_t imageSize, uint32_t padding, const Byte* bytes) :
|
||||
_numFaces(1),
|
||||
_imageSize(imageSize),
|
||||
_padding(padding),
|
||||
_faceSize(imageSize),
|
||||
_padding(padding),
|
||||
_faceBytes(1, bytes) {}
|
||||
|
||||
Image(uint32_t pageSize, uint32_t padding, const FaceBytes& cubeFaceBytes) :
|
||||
_numFaces(NUM_CUBEMAPFACES),
|
||||
_imageSize(pageSize * NUM_CUBEMAPFACES),
|
||||
_padding(padding),
|
||||
_faceSize(pageSize)
|
||||
_faceSize(pageSize),
|
||||
_padding(padding)
|
||||
{
|
||||
if (cubeFaceBytes.size() == NUM_CUBEMAPFACES) {
|
||||
_faceBytes = cubeFaceBytes;
|
||||
|
@ -420,7 +420,7 @@ namespace ktx {
|
|||
using Images = std::vector<Image>;
|
||||
|
||||
class KTX {
|
||||
void resetStorage(StoragePointer& src);
|
||||
void resetStorage(const StoragePointer& src);
|
||||
|
||||
KTX();
|
||||
public:
|
||||
|
@ -448,7 +448,7 @@ namespace ktx {
|
|||
static Images writeImages(Byte* destBytes, size_t destByteSize, const Images& images);
|
||||
|
||||
// Parse a block of memory and create a KTX object from it
|
||||
static std::unique_ptr<KTX> create(StoragePointer& src);
|
||||
static std::unique_ptr<KTX> create(const StoragePointer& src);
|
||||
|
||||
static bool checkHeaderFromStorage(size_t srcSize, const Byte* srcBytes);
|
||||
static Images parseImages(const Header& header, size_t srcSize, const Byte* srcBytes);
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <list>
|
||||
#include <QtGlobal>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#define NOEXCEPT noexcept
|
||||
|
@ -68,7 +69,7 @@ namespace ktx {
|
|||
}
|
||||
|
||||
// find the first null character \0
|
||||
int keyLength = 0;
|
||||
uint32_t keyLength = 0;
|
||||
while (reinterpret_cast<const char*>(src[++keyLength]) != '\0') {
|
||||
if (keyLength == keyValueByteSize) {
|
||||
// key must be null-terminated, and there must be space for the value
|
||||
|
@ -119,8 +120,8 @@ namespace ktx {
|
|||
|
||||
return true;
|
||||
}
|
||||
catch (ReaderException& e) {
|
||||
qWarning(e.what());
|
||||
catch (const ReaderException& e) {
|
||||
qWarning() << e.what();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +129,6 @@ namespace ktx {
|
|||
Images KTX::parseImages(const Header& header, size_t srcSize, const Byte* srcBytes) {
|
||||
Images images;
|
||||
auto currentPtr = srcBytes;
|
||||
auto numMips = header.getNumberOfLevels();
|
||||
auto numFaces = header.numberOfFaces;
|
||||
|
||||
// Keep identifying new mip as long as we can at list query the next imageSize
|
||||
|
@ -163,7 +163,7 @@ namespace ktx {
|
|||
return images;
|
||||
}
|
||||
|
||||
std::unique_ptr<KTX> KTX::create(StoragePointer& src) {
|
||||
std::unique_ptr<KTX> KTX::create(const StoragePointer& src) {
|
||||
if (!src) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -105,14 +105,14 @@ namespace ktx {
|
|||
|
||||
// Single face vs cubes
|
||||
if (srcImages[l]._numFaces == 1) {
|
||||
auto copied = memcpy(currentPtr, srcImages[l]._faceBytes[0], imageSize);
|
||||
memcpy(currentPtr, srcImages[l]._faceBytes[0], imageSize);
|
||||
destImages.emplace_back(Image((uint32_t) imageSize, padding, currentPtr));
|
||||
currentPtr += imageSize;
|
||||
} else {
|
||||
Image::FaceBytes faceBytes(6);
|
||||
auto faceSize = srcImages[l]._faceSize;
|
||||
for (int face = 0; face < 6; face++) {
|
||||
auto copied = memcpy(currentPtr, srcImages[l]._faceBytes[face], faceSize);
|
||||
memcpy(currentPtr, srcImages[l]._faceBytes[face], faceSize);
|
||||
faceBytes[face] = currentPtr;
|
||||
currentPtr += faceSize;
|
||||
}
|
||||
|
|
|
@ -186,6 +186,39 @@ NetworkTexturePointer TextureCache::getTexture(const QUrl& url, Type type, const
|
|||
return ResourceCache::getResource(url, QUrl(), &extra).staticCast<NetworkTexture>();
|
||||
}
|
||||
|
||||
gpu::TexturePointer getFallbackTextureForType(NetworkTexture::Type type) {
|
||||
auto textureCache = DependencyManager::get<TextureCache>();
|
||||
|
||||
gpu::TexturePointer result;
|
||||
switch (type) {
|
||||
case NetworkTexture::DEFAULT_TEXTURE:
|
||||
case NetworkTexture::ALBEDO_TEXTURE:
|
||||
case NetworkTexture::ROUGHNESS_TEXTURE:
|
||||
case NetworkTexture::OCCLUSION_TEXTURE:
|
||||
result = textureCache->getWhiteTexture();
|
||||
break;
|
||||
|
||||
case NetworkTexture::NORMAL_TEXTURE:
|
||||
result = textureCache->getBlueTexture();
|
||||
break;
|
||||
|
||||
case NetworkTexture::EMISSIVE_TEXTURE:
|
||||
case NetworkTexture::LIGHTMAP_TEXTURE:
|
||||
result = textureCache->getBlackTexture();
|
||||
break;
|
||||
|
||||
case NetworkTexture::BUMP_TEXTURE:
|
||||
case NetworkTexture::SPECULAR_TEXTURE:
|
||||
case NetworkTexture::GLOSS_TEXTURE:
|
||||
case NetworkTexture::CUBE_TEXTURE:
|
||||
case NetworkTexture::CUSTOM_TEXTURE:
|
||||
case NetworkTexture::STRICT_TEXTURE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
NetworkTexture::TextureLoaderFunc getTextureLoaderForType(NetworkTexture::Type type,
|
||||
const QVariantMap& options = QVariantMap()) {
|
||||
|
@ -299,6 +332,13 @@ NetworkTexture::TextureLoaderFunc NetworkTexture::getTextureLoader() const {
|
|||
return getTextureLoaderForType(_type);
|
||||
}
|
||||
|
||||
gpu::TexturePointer NetworkTexture::getFallbackTexture() const {
|
||||
if (_type == CUSTOM_TEXTURE) {
|
||||
return gpu::TexturePointer();
|
||||
}
|
||||
return getFallbackTextureForType(_type);
|
||||
}
|
||||
|
||||
|
||||
class ImageReader : public QRunnable {
|
||||
public:
|
||||
|
@ -428,7 +468,11 @@ void ImageReader::run() {
|
|||
auto url = _url.toString().toStdString();
|
||||
|
||||
PROFILE_RANGE_EX(resource_parse_image, __FUNCTION__, 0xffffff00, 0);
|
||||
texture.reset(resource.dynamicCast<NetworkTexture>()->getTextureLoader()(image, url));
|
||||
auto networkTexture = resource.dynamicCast<NetworkTexture>();
|
||||
texture.reset(networkTexture->getTextureLoader()(image, url));
|
||||
if (texture) {
|
||||
texture->setFallbackTexture(networkTexture->getFallbackTexture());
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the resource has not been deleted
|
||||
|
|
|
@ -75,6 +75,7 @@ public:
|
|||
Type getTextureType() const { return _type; }
|
||||
|
||||
TextureLoaderFunc getTextureLoader() const;
|
||||
gpu::TexturePointer getFallbackTexture() const;
|
||||
|
||||
signals:
|
||||
void networkTextureCreated(const QWeakPointer<NetworkTexture>& self);
|
||||
|
|
|
@ -116,12 +116,10 @@ gpu::Texture* cacheTexture(const std::string& name, gpu::Texture* srcTexture, bo
|
|||
auto ktxMemory = gpu::Texture::serialize(*srcTexture);
|
||||
if (ktxMemory) {
|
||||
const auto& ktxStorage = ktxMemory->getStorage();
|
||||
auto header = ktxMemory->getHeader();
|
||||
QFile outFile(cacheFilename.c_str());
|
||||
if (!outFile.open(QFile::Truncate | QFile::ReadWrite)) {
|
||||
throw std::runtime_error("Unable to open file");
|
||||
}
|
||||
//auto ktxSize = sizeof(ktx::Header); // ktxStorage->size()
|
||||
auto ktxSize = ktxStorage->size();
|
||||
outFile.resize(ktxSize);
|
||||
auto dest = outFile.map(0, ktxSize);
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#include <StatTracker.h>
|
||||
#include <LogHandler.h>
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include <gpu/Texture.h>
|
||||
#include <gl/Config.h>
|
||||
#include <model/TextureMap.h>
|
||||
|
@ -99,12 +99,10 @@ int main(int argc, char** argv) {
|
|||
auto ktxMemory = gpu::Texture::serialize(*testTexture);
|
||||
{
|
||||
const auto& ktxStorage = ktxMemory->getStorage();
|
||||
auto header = ktxMemory->getHeader();
|
||||
QFile outFile(TEST_IMAGE_KTX);
|
||||
if (!outFile.open(QFile::Truncate | QFile::ReadWrite)) {
|
||||
throw std::runtime_error("Unable to open file");
|
||||
}
|
||||
//auto ktxSize = sizeof(ktx::Header); // ktxStorage->size()
|
||||
auto ktxSize = ktxStorage->size();
|
||||
outFile.resize(ktxSize);
|
||||
auto dest = outFile.map(0, ktxSize);
|
||||
|
|
Loading…
Reference in a new issue