Only upload textures from the main thread.

This commit is contained in:
Leonardo 2017-12-22 05:42:28 -08:00
parent a57c6275c0
commit 880f8f9a47
5 changed files with 67 additions and 42 deletions

View file

@ -1687,6 +1687,22 @@ void lcPiecesLibrary::ReleaseTexture(lcTexture* Texture)
} }
} }
void lcPiecesLibrary::QueueTextureUpload(lcTexture* Texture)
{
QMutexLocker Lock(&mTextureMutex);
mTextureUploads.push_back(Texture);
}
void lcPiecesLibrary::UploadTextures()
{
QMutexLocker Lock(&mTextureMutex);
for (lcTexture* Texture : mTextureUploads)
Texture->Upload();
mTextureUploads.clear();
}
bool lcPiecesLibrary::LoadPrimitive(lcLibraryPrimitive* Primitive) bool lcPiecesLibrary::LoadPrimitive(lcLibraryPrimitive* Primitive)
{ {
mLoadMutex.lock(); mLoadMutex.lock();

View file

@ -179,6 +179,8 @@ public:
lcTexture* FindTexture(const char* TextureName, Project* CurrentProject, bool SearchProjectFolder); lcTexture* FindTexture(const char* TextureName, Project* CurrentProject, bool SearchProjectFolder);
bool LoadTexture(lcTexture* Texture); bool LoadTexture(lcTexture* Texture);
void ReleaseTexture(lcTexture* Texture); void ReleaseTexture(lcTexture* Texture);
void QueueTextureUpload(lcTexture* Texture);
void UploadTextures();
bool PieceInCategory(PieceInfo* Info, const char* CategoryKeywords) const; bool PieceInCategory(PieceInfo* Info, const char* CategoryKeywords) const;
void GetCategoryEntries(int CategoryIndex, bool GroupPieces, lcArray<PieceInfo*>& SinglePieces, lcArray<PieceInfo*>& GroupedPieces); void GetCategoryEntries(int CategoryIndex, bool GroupPieces, lcArray<PieceInfo*>& SinglePieces, lcArray<PieceInfo*>& GroupedPieces);
@ -246,6 +248,9 @@ protected:
QList<QFuture<void>> mLoadFutures; QList<QFuture<void>> mLoadFutures;
QList<PieceInfo*> mLoadQueue; QList<PieceInfo*> mLoadQueue;
QMutex mTextureMutex;
std::vector<lcTexture*> mTextureUploads;
QString mCachePath; QString mCachePath;
qint64 mArchiveCheckSum[4]; qint64 mArchiveCheckSum[4];
QString mLibraryFileName; QString mLibraryFileName;

View file

@ -219,7 +219,9 @@ void lcScene::DrawRenderMeshes(lcContext* Context, int PrimitiveTypes, bool Enab
void lcScene::Draw(lcContext* Context) const void lcScene::Draw(lcContext* Context) const
{ {
lcGetPiecesLibrary()->UpdateBuffers(Context); // TODO: find a better place for this update // TODO: find a better place for these updates
lcGetPiecesLibrary()->UpdateBuffers(Context);
lcGetPiecesLibrary()->UploadTextures();
Context->SetViewMatrix(mViewMatrix); Context->SetViewMatrix(mViewMatrix);

View file

@ -27,7 +27,7 @@ lcTexture* lcLoadTexture(const QString& FileName, int Flags)
void lcReleaseTexture(lcTexture* Texture) void lcReleaseTexture(lcTexture* Texture)
{ {
if (Texture && Texture->Release() == 0) if (Texture && !Texture->Release())
delete Texture; delete Texture;
} }
@ -46,12 +46,12 @@ lcTexture::~lcTexture()
void lcTexture::CreateGridTexture() void lcTexture::CreateGridTexture()
{ {
const int NumLevels = 9; const int NumLevels = 9;
Image GridImages[NumLevels]; mImages.resize(NumLevels);
quint8* Previous = nullptr; quint8* Previous = nullptr;
for (int ImageLevel = 0; ImageLevel < NumLevels; ImageLevel++) for (int ImageLevel = 0; ImageLevel < NumLevels; ImageLevel++)
{ {
Image& GridImage = GridImages[ImageLevel]; Image& GridImage = mImages[ImageLevel];
const int GridSize = 256 >> ImageLevel; const int GridSize = 256 >> ImageLevel;
GridImage.Allocate(GridSize, GridSize, LC_PIXEL_FORMAT_A8); GridImage.Allocate(GridSize, GridSize, LC_PIXEL_FORMAT_A8);
@ -156,9 +156,10 @@ void lcTexture::CreateGridTexture()
Previous = GridImage.mData; Previous = GridImage.mData;
} }
Load(GridImages, NumLevels, LC_TEXTURE_WRAPU | LC_TEXTURE_WRAPV | LC_TEXTURE_MIPMAPS | LC_TEXTURE_ANISOTROPIC);
mRefCount = 1; mRefCount = 1;
mFlags = LC_TEXTURE_WRAPU | LC_TEXTURE_WRAPV | LC_TEXTURE_MIPMAPS | LC_TEXTURE_ANISOTROPIC;
lcGetPiecesLibrary()->QueueTextureUpload(this);
} }
bool lcTexture::Load() bool lcTexture::Load()
@ -168,28 +169,28 @@ bool lcTexture::Load()
bool lcTexture::Load(const QString& FileName, int Flags) bool lcTexture::Load(const QString& FileName, int Flags)
{ {
Image image; mImages.resize(1);
if (!image.FileLoad(FileName)) if (!mImages[0].FileLoad(FileName))
return false; return false;
return Load(image, Flags); return Load(Flags);
} }
bool lcTexture::Load(lcMemFile& File, int Flags) bool lcTexture::Load(lcMemFile& File, int Flags)
{ {
Image image; mImages.resize(1);
if (!image.FileLoad(File)) if (!mImages[0].FileLoad(File))
return false; return false;
return Load(image, Flags); return Load(Flags);
} }
bool lcTexture::Load(Image* images, int NumLevels, int Flags) // todo: this should be part of lcContext, it can be called from multiple threads void lcTexture::Upload()
{ {
mWidth = images[0].mWidth; mWidth = mImages[0].mWidth;
mHeight = images[0].mHeight; mHeight = mImages[0].mHeight;
glGenTextures(1, &mTexture); glGenTextures(1, &mTexture);
@ -199,13 +200,13 @@ bool lcTexture::Load(Image* images, int NumLevels, int Flags) // todo: this shou
{ GL_NEAREST, GL_LINEAR, GL_LINEAR, GL_LINEAR, GL_LINEAR }, { GL_NEAREST, GL_LINEAR, GL_LINEAR, GL_LINEAR, GL_LINEAR },
}; };
int FilterFlags = Flags & LC_TEXTURE_FILTER_MASK; int FilterFlags = mFlags & LC_TEXTURE_FILTER_MASK;
int FilterIndex = FilterFlags >> LC_TEXTURE_FILTER_SHIFT; int FilterIndex = FilterFlags >> LC_TEXTURE_FILTER_SHIFT;
int MipIndex = Flags & LC_TEXTURE_MIPMAPS ? 0 : 1; int MipIndex = mFlags & LC_TEXTURE_MIPMAPS ? 0 : 1;
glBindTexture(GL_TEXTURE_2D, mTexture); glBindTexture(GL_TEXTURE_2D, mTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (Flags & LC_TEXTURE_WRAPU) ? GL_REPEAT : GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (mFlags & LC_TEXTURE_WRAPU) ? GL_REPEAT : GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (Flags & LC_TEXTURE_WRAPV) ? GL_REPEAT : GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (mFlags & LC_TEXTURE_WRAPV) ? GL_REPEAT : GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filters[MipIndex][FilterIndex]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filters[MipIndex][FilterIndex]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filters[1][FilterIndex]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filters[1][FilterIndex]);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
@ -214,7 +215,7 @@ bool lcTexture::Load(Image* images, int NumLevels, int Flags) // todo: this shou
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, lcMin(4.0f, gMaxAnisotropy)); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, lcMin(4.0f, gMaxAnisotropy));
int Format; int Format;
switch (images[0].mFormat) switch (mImages[0].mFormat)
{ {
default: default:
case LC_PIXEL_FORMAT_INVALID: case LC_PIXEL_FORMAT_INVALID:
@ -234,15 +235,15 @@ bool lcTexture::Load(Image* images, int NumLevels, int Flags) // todo: this shou
break; break;
} }
void* Data = images[0].mData; void* Data = mImages[0].mData;
glTexImage2D(GL_TEXTURE_2D, 0, Format, mWidth, mHeight, 0, Format, GL_UNSIGNED_BYTE, Data); glTexImage2D(GL_TEXTURE_2D, 0, Format, mWidth, mHeight, 0, Format, GL_UNSIGNED_BYTE, Data);
int MaxLevel = 0; int MaxLevel = 0;
if (Flags & LC_TEXTURE_MIPMAPS) if (mFlags & LC_TEXTURE_MIPMAPS)
{ {
int Width = mWidth; int Width = mWidth;
int Height = mHeight; int Height = mHeight;
int Components = images[0].GetBPP(); int Components = mImages[0].GetBPP();
for (int Level = 1; ((Width != 1) || (Height != 1)); Level++) for (int Level = 1; ((Width != 1) || (Height != 1)); Level++)
{ {
@ -251,7 +252,7 @@ bool lcTexture::Load(Image* images, int NumLevels, int Flags) // todo: this shou
Width = lcMax(1, Width >> 1); Width = lcMax(1, Width >> 1);
Height = lcMax(1, Height >> 1); Height = lcMax(1, Height >> 1);
if (NumLevels == 1) if (mImages.size() == 1)
{ {
GLubyte *Out, *In; GLubyte *Out, *In;
@ -263,7 +264,7 @@ bool lcTexture::Load(Image* images, int NumLevels, int Flags) // todo: this shou
Out[c] = (In[c] + In[c + Components] + In[RowStride] + In[c + RowStride + Components]) / 4; Out[c] = (In[c] + In[c + Components] + In[RowStride] + In[c + RowStride + Components]) / 4;
} }
else else
Data = images[Level].mData; Data = mImages[Level].mData;
glTexImage2D(GL_TEXTURE_2D, Level, Format, Width, Height, 0, Format, GL_UNSIGNED_BYTE, Data); glTexImage2D(GL_TEXTURE_2D, Level, Format, Width, Height, 0, Format, GL_UNSIGNED_BYTE, Data);
MaxLevel++; MaxLevel++;
@ -272,15 +273,16 @@ bool lcTexture::Load(Image* images, int NumLevels, int Flags) // todo: this shou
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, MaxLevel); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, MaxLevel);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
return true;
} }
bool lcTexture::Load(Image& image, int Flags) bool lcTexture::Load(int Flags)
{ {
image.ResizePow2(); for (Image& Image : mImages)
Image.ResizePow2();
mFlags = Flags;
return Load(&image, 1, Flags); lcGetPiecesLibrary()->QueueTextureUpload(this);
return true;
} }
void lcTexture::Unload() void lcTexture::Unload()

View file

@ -14,7 +14,7 @@
#define LC_TEXTURE_NAME_LEN 256 #define LC_TEXTURE_NAME_LEN 256
class Image; #include "image.h"
class lcTexture class lcTexture
{ {
@ -26,28 +26,25 @@ public:
bool Load(const QString& FileName, int Flags = 0); bool Load(const QString& FileName, int Flags = 0);
bool Load(lcMemFile& File, int Flags = 0); bool Load(lcMemFile& File, int Flags = 0);
bool Load(Image& image, int Flags); void Upload();
bool Load(Image* images, int NumLevels, int Flags);
void Unload(); void Unload();
int AddRef() void AddRef()
{ {
mRefCount++; mRefCount.ref();
if (mRefCount == 1) if (mRefCount == 1)
Load(); Load();
return mRefCount;
} }
int Release() bool Release()
{ {
mRefCount--; bool InUse = mRefCount.deref();
if (!mRefCount) if (!InUse)
Unload(); Unload();
return mRefCount; return InUse;
} }
void SetTemporary(bool Temporary) void SetTemporary(bool Temporary)
@ -67,9 +64,12 @@ public:
protected: protected:
bool Load(); bool Load();
bool Load(int Flags);
bool mTemporary; bool mTemporary;
int mRefCount; QAtomicInt mRefCount;
std::vector<Image> mImages;
int mFlags;
}; };
lcTexture* lcLoadTexture(const QString& FileName, int Flags); lcTexture* lcLoadTexture(const QString& FileName, int Flags);