Merge pull request #9803 from jherico/smarter_textures

Throttle texture creation
This commit is contained in:
samcake 2017-03-06 14:13:10 -08:00 committed by GitHub
commit 9ae750b749
17 changed files with 93 additions and 39 deletions

View file

@ -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;

View file

@ -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

View file

@ -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];

View file

@ -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;

View file

@ -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;

View file

@ -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() {

View file

@ -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);

View file

@ -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;

View file

@ -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;
}

View file

@ -77,7 +77,7 @@ KTX::KTX() {
KTX::~KTX() {
}
void KTX::resetStorage(StoragePointer& storage) {
void KTX::resetStorage(const StoragePointer& storage) {
_storage = storage;
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -75,6 +75,7 @@ public:
Type getTextureType() const { return _type; }
TextureLoaderFunc getTextureLoader() const;
gpu::TexturePointer getFallbackTexture() const;
signals:
void networkTextureCreated(const QWeakPointer<NetworkTexture>& self);

View file

@ -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);

View file

@ -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);