mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2025-10-04 05:13:19 +00:00
Merge branch 'experimental'
This commit is contained in:
commit
cccd42227f
41 changed files with 1335 additions and 1122 deletions
|
@ -113,6 +113,13 @@ void AfterEffectManager::deleteShaders()
|
|||
}
|
||||
}
|
||||
|
||||
void AfterEffectManager::unloadShaders()
|
||||
{
|
||||
for(size_t i = 0; i < loadedShaders.size(); ++i)
|
||||
if(loadedShaders[i])
|
||||
loadedShaders[i]->unload();
|
||||
}
|
||||
|
||||
void AfterEffectManager::clear()
|
||||
{
|
||||
deleteEffects();
|
||||
|
@ -196,7 +203,7 @@ void AfterEffectManager::renderGrid()
|
|||
Shader *activeShader = 0;
|
||||
for (size_t i = 0; i < shaderPipeline.size(); ++i)
|
||||
{
|
||||
if(shaderPipeline[i])
|
||||
if(shaderPipeline[i] && shaderPipeline[i]->isLoaded())
|
||||
{
|
||||
if(firstShader < 0)
|
||||
{
|
||||
|
@ -275,7 +282,7 @@ void AfterEffectManager::renderGrid()
|
|||
for(int i = firstShader + 1; i <= lastShader; ++i)
|
||||
{
|
||||
activeShader = shaderPipeline[i];
|
||||
if(!activeShader)
|
||||
if(!(activeShader && activeShader->isLoaded()))
|
||||
continue;
|
||||
|
||||
// Swap and exchange framebuffers. The old output buffer serves as texture input for the other one
|
||||
|
@ -373,7 +380,7 @@ void AfterEffectManager::renderGridPoints()
|
|||
void AfterEffectManager::unloadDevice()
|
||||
{
|
||||
backupBuffer.unloadDevice();
|
||||
deleteShaders();
|
||||
unloadShaders();
|
||||
}
|
||||
|
||||
void AfterEffectManager::reloadDevice()
|
||||
|
@ -399,7 +406,22 @@ void AfterEffectManager::reloadDevice()
|
|||
else
|
||||
backupBuffer.init(-1, -1, true);
|
||||
|
||||
loadShaders();
|
||||
for (size_t i = 0; i < loadedShaders.size(); ++i)
|
||||
{
|
||||
if (Shader *sh = loadedShaders[i])
|
||||
{
|
||||
sh->reload();
|
||||
if (!sh->isLoaded())
|
||||
{
|
||||
debugLog("AfterEffect::reloadDevice(): Failed to reload shader");
|
||||
delete sh;
|
||||
loadedShaders[i] = 0;
|
||||
for(size_t j = 0; j < shaderPipeline.size(); ++j)
|
||||
if(sh == shaderPipeline[j])
|
||||
shaderPipeline[j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AfterEffectManager::addEffect(Effect *e)
|
||||
|
@ -612,7 +634,7 @@ int AfterEffectManager::_insertShader(Shader *sh)
|
|||
return loadedShaders.size();
|
||||
}
|
||||
|
||||
void AfterEffectManager::unloadShader(int handle)
|
||||
void AfterEffectManager::deleteShader(int handle)
|
||||
{
|
||||
Shader *sh = getShaderPtr(handle);
|
||||
if(!sh)
|
||||
|
|
|
@ -91,6 +91,7 @@ public:
|
|||
void renderGridPoints();
|
||||
|
||||
void loadShaders();
|
||||
void unloadShaders(); // unloads shaders but keeps code and data intact, so that they can be reloaded.
|
||||
void deleteShaders();
|
||||
|
||||
void unloadDevice();
|
||||
|
@ -116,7 +117,7 @@ public:
|
|||
Shader *getShaderPtr(int handle);
|
||||
void setShaderPipelineSize(size_t size);
|
||||
bool setShaderPipelinePos(int handle, size_t pos);
|
||||
void unloadShader(int handle);
|
||||
void deleteShader(int handle);
|
||||
|
||||
protected:
|
||||
int _insertShader(Shader *sh);
|
||||
|
|
|
@ -12,6 +12,7 @@ public:
|
|||
virtual void setText(const std::string& text) = 0;
|
||||
virtual void setWidth(int width) = 0;
|
||||
virtual void setFontSize(int sz) = 0;
|
||||
virtual void setAlign(Align a) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ public:
|
|||
bool isScrollingText();
|
||||
void stopScrollingText();
|
||||
bool isEmpty();
|
||||
void setAlign(Align align);
|
||||
virtual void setAlign(Align align);
|
||||
std::string getText();
|
||||
int getWidthOnScreen();
|
||||
void loadSpacingMap(const std::string &file);
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
void setWidth(int width);
|
||||
void setFontSize(int sz);
|
||||
int getNumLines() { return lines.size(); }
|
||||
void setAlign(Align align);
|
||||
virtual void setAlign(Align align);
|
||||
protected:
|
||||
int fontDrawSize, textWidth;
|
||||
void formatText();
|
||||
|
|
291
BBGE/MemoryAllocatorSmallBlock.cpp
Normal file
291
BBGE/MemoryAllocatorSmallBlock.cpp
Normal file
|
@ -0,0 +1,291 @@
|
|||
// Public domain
|
||||
|
||||
// Aquaria specific...
|
||||
#include "Base.h"
|
||||
|
||||
#include "algorithmx.h"
|
||||
#include "MemoryAllocatorSmallBlock.h"
|
||||
#include "bithacks.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
//#define DD(...) fprintf(stderr, __VA_ARGS__)
|
||||
#define DD(...)
|
||||
#define logdev(...)
|
||||
#define logerror(...)
|
||||
|
||||
#ifdef NDEBUG
|
||||
# define ASSERT(x)
|
||||
#else
|
||||
# define ASSERT(x) assert(x)
|
||||
#endif
|
||||
|
||||
|
||||
SmallBlockAllocator::SmallBlockAllocator(unsigned int blockSizeMin,
|
||||
unsigned int blockSizeMax,
|
||||
unsigned int blockSizeIncr /* = 8 */,
|
||||
unsigned int elemsPerBlockMin /* = 64 */,
|
||||
unsigned int elemsPerBlockMax /* = 2048 */)
|
||||
: _blockSizeMin(blockSizeMin)
|
||||
, _blockSizeMax(blockSizeMax)
|
||||
, _blockSizeIncr(blockSizeIncr)
|
||||
, _elemsPerBlockMin(elemsPerBlockMin)
|
||||
, _elemsPerBlockMax(elemsPerBlockMax)
|
||||
{
|
||||
ASSERT(_blockSizeIncr % 4 == 0); // less than 4 bytes makes no sense
|
||||
ASSERT(_blockSizeMin % _blockSizeIncr == 0);
|
||||
ASSERT(_blockSizeMax % _blockSizeIncr == 0);
|
||||
ASSERT((_blockSizeMax - _blockSizeMin) % _blockSizeIncr == 0);
|
||||
unsigned int c = ((_blockSizeMax - _blockSizeMin) / _blockSizeIncr) + 1;
|
||||
logdev("SBA: Using %u distinct block sizes from %u - %u bytes", c, _blockSizeMin, _blockSizeMax);
|
||||
_blocks = new Block*[c]; // TODO: Do we really want to use dynamic allocation here?
|
||||
memset(_blocks, 0, c * sizeof(Block*));
|
||||
}
|
||||
|
||||
SmallBlockAllocator::~SmallBlockAllocator()
|
||||
{
|
||||
while(_allblocks.size())
|
||||
{
|
||||
Block *blk = _allblocks.back();
|
||||
logerror("~SmallBlockAllocator(): Warning: Leftover block with %u/%u elements, %uB each",
|
||||
blk->maxElems, blk->maxElems - blk->freeElems, blk->elemSize);
|
||||
_FreeBlock(blk);
|
||||
}
|
||||
delete [] _blocks;
|
||||
}
|
||||
|
||||
void *SmallBlockAllocator::Alloc(void *ptr, size_t newsize, size_t oldsize)
|
||||
{
|
||||
DD("SBA::Alloc() ptr = %p; newsize = %u, oldsize = %u", ptr, newsize, oldsize);
|
||||
|
||||
if(ptr)
|
||||
{
|
||||
if(!newsize)
|
||||
{
|
||||
_Free(ptr, oldsize);
|
||||
return NULL;
|
||||
}
|
||||
else if(newsize == oldsize)
|
||||
return ptr;
|
||||
else
|
||||
return _Realloc(ptr, newsize, oldsize);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(newsize)
|
||||
return _Alloc(newsize);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SmallBlockAllocator::Block *SmallBlockAllocator::_AllocBlock(unsigned int elemCount, unsigned int elemSize)
|
||||
{
|
||||
DD("SBA: _AllocBlock: elemCount = %u, elemSize = %u", elemCount, elemSize);
|
||||
|
||||
const unsigned int bitsPerInt = (sizeof(unsigned int) * 8); // 32
|
||||
unsigned int bitmapInts = (elemCount + (bitsPerInt - 1)) / bitsPerInt;
|
||||
void *ptr = malloc(
|
||||
(sizeof(Block) - sizeof(unsigned int)) // block header without bitmap[1]
|
||||
+ (bitmapInts * sizeof(unsigned int)) // actual bitmap size
|
||||
+ (elemCount * elemSize) // data size
|
||||
);
|
||||
|
||||
if(!ptr)
|
||||
return NULL;
|
||||
Block *blk = (Block*)ptr;
|
||||
memset(&blk->bitmap[0], 0xff, bitmapInts * sizeof(unsigned int)); // all free
|
||||
blk->elemSize = elemSize;
|
||||
blk->maxElems = elemCount;
|
||||
blk->freeElems = elemCount;
|
||||
blk->bitmapInts = bitmapInts;
|
||||
blk->next = NULL;
|
||||
blk->prev = NULL;
|
||||
|
||||
// using insertion sort
|
||||
std::vector<Block*>::iterator insertit = std::lower_bound(_allblocks.begin(), _allblocks.end(), blk);
|
||||
_allblocks.insert(insertit, blk);
|
||||
|
||||
return blk;
|
||||
}
|
||||
|
||||
void SmallBlockAllocator::_FreeBlock(Block *blk)
|
||||
{
|
||||
DD("SBA: _FreeBlock: elemCount = %u, elemSize = %u", blk->maxElems, blk->elemSize);
|
||||
|
||||
if(blk->prev)
|
||||
blk->prev->next = blk->next;
|
||||
else
|
||||
_blocks[GetIndexForElemSize(blk->elemSize)] = blk->next;
|
||||
|
||||
if(blk->next)
|
||||
blk->next->prev = blk->prev;
|
||||
|
||||
free(blk);
|
||||
|
||||
// keeps the vector sorted
|
||||
_allblocks.erase(std::remove(_allblocks.begin(), _allblocks.end(), blk), _allblocks.end());
|
||||
}
|
||||
|
||||
|
||||
SmallBlockAllocator::Block *SmallBlockAllocator::_AppendBlock(unsigned int elemSize)
|
||||
{
|
||||
unsigned int idx = GetIndexForElemSize(elemSize);
|
||||
Block *blk = _blocks[idx];
|
||||
unsigned int elemsPerBlock = _elemsPerBlockMin;
|
||||
if(blk)
|
||||
{
|
||||
while(blk->next)
|
||||
blk = blk->next;
|
||||
elemsPerBlock = blk->maxElems * 2; // new block is double the size
|
||||
if(elemsPerBlock > _elemsPerBlockMax)
|
||||
elemsPerBlock = _elemsPerBlockMax;
|
||||
}
|
||||
|
||||
unsigned int blockElemSize = ((elemSize + (_blockSizeIncr - 1)) / _blockSizeIncr) * _blockSizeIncr;
|
||||
ASSERT(blockElemSize >= elemSize);
|
||||
|
||||
Block *newblk = _AllocBlock(elemsPerBlock, blockElemSize);
|
||||
if(!newblk)
|
||||
return NULL;
|
||||
|
||||
if(blk)
|
||||
{
|
||||
blk->next = newblk; // append to list
|
||||
newblk->prev = blk;
|
||||
}
|
||||
else
|
||||
_blocks[idx] = newblk; // list head
|
||||
|
||||
return newblk;
|
||||
}
|
||||
|
||||
SmallBlockAllocator::Block *SmallBlockAllocator::_GetFreeBlock(unsigned int elemSize)
|
||||
{
|
||||
unsigned int idx = GetIndexForElemSize(elemSize);
|
||||
Block *blk = _blocks[idx];
|
||||
while(blk && !blk->freeElems)
|
||||
blk = blk->next;
|
||||
return blk;
|
||||
}
|
||||
|
||||
void *SmallBlockAllocator::Block::allocElem()
|
||||
{
|
||||
ASSERT(freeElems);
|
||||
unsigned int i = 0;
|
||||
for( ; !bitmap[i]; ++i) // as soon as one isn't all zero, there's a free slot
|
||||
ASSERT(i < bitmapInts);
|
||||
ASSERT(i < bitmapInts);
|
||||
int freeidx = bithacks::ctz(bitmap[i]);
|
||||
ASSERT(bitmap[i] & (1 << freeidx)); // make sure this is '1' (= free)
|
||||
bitmap[i] &= ~(1 << freeidx); // put '0' where '1' was (-> mark as non-free)
|
||||
--freeElems;
|
||||
const unsigned int offs = (i * sizeof(unsigned int) * 8 * elemSize); // skip forward i bitmaps (32 elems each)
|
||||
unsigned char *ret = getPtr() + offs + (elemSize * freeidx);
|
||||
ASSERT(contains(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool SmallBlockAllocator::Block::contains(unsigned char *ptr) const
|
||||
{
|
||||
const unsigned char *pp = getPtr();
|
||||
|
||||
if(ptr < pp)
|
||||
return false; // pointer is out of range (1)
|
||||
if(ptr >= pp + (maxElems * elemSize))
|
||||
return false; // pointer is out of range (2)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SmallBlockAllocator::Block::freeElem(unsigned char *ptr)
|
||||
{
|
||||
ASSERT(contains(ptr));
|
||||
ASSERT(freeElems < maxElems); // make sure the block is not all free
|
||||
|
||||
const ptrdiff_t p = ptr - getPtr();
|
||||
ASSERT((p % elemSize) == 0); // make sure alignment is right
|
||||
const unsigned int idx = p / elemSize;
|
||||
const unsigned int bitsPerInt = sizeof(unsigned int) * 8; // 32
|
||||
const unsigned int bitmapIdx = idx / bitsPerInt;
|
||||
const unsigned int bitIdx = idx % bitsPerInt;
|
||||
ASSERT(bitmapIdx < bitmapInts);
|
||||
ASSERT(!(bitmap[bitmapIdx] & (1 << bitIdx))); // make sure this is '0' (= used)
|
||||
|
||||
bitmap[bitmapIdx] |= (1 << bitIdx); // put '1' where '0' was (-> mark as free)
|
||||
++freeElems;
|
||||
|
||||
#ifdef _DEBUG
|
||||
memset(ptr, 0xfa, elemSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
void *SmallBlockAllocator::_FallbackAlloc(unsigned int size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void SmallBlockAllocator::_FallbackFree(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
void *SmallBlockAllocator::_Alloc(unsigned int size)
|
||||
{
|
||||
if(size > _blockSizeMax)
|
||||
return _FallbackAlloc(size);
|
||||
|
||||
Block *blk = _GetFreeBlock(size);
|
||||
ASSERT(!blk || blk->freeElems);
|
||||
if(!blk)
|
||||
{
|
||||
blk = _AppendBlock(size);
|
||||
if(!blk)
|
||||
return _FallbackAlloc(size);
|
||||
}
|
||||
return blk->allocElem();
|
||||
}
|
||||
|
||||
bool SmallBlockAllocator::Block_ptr_cmp(const Block *blk, const void *ptr)
|
||||
{
|
||||
return blk->getEndPtr() < ((unsigned char*)ptr);
|
||||
}
|
||||
|
||||
SmallBlockAllocator::Block *SmallBlockAllocator::_FindBlockContainingPtr(void *ptr)
|
||||
{
|
||||
// MSVC's std::lower_bound uses iterator debug checks in debug mode,
|
||||
// which breaks Block_ptr_cmp() because the left and right types are different.
|
||||
std::vector<Block*>::iterator it = stdx_fg::lower_bound(_allblocks.begin(), _allblocks.end(), ptr, Block_ptr_cmp);
|
||||
return (it != _allblocks.end() && (*it)->contains((unsigned char*)ptr)) ? *it : NULL;
|
||||
}
|
||||
|
||||
void SmallBlockAllocator::_Free(void *ptr, unsigned int size)
|
||||
{
|
||||
if(size <= _blockSizeMax)
|
||||
{
|
||||
Block *blk = _FindBlockContainingPtr(ptr);
|
||||
if(blk)
|
||||
{
|
||||
ASSERT(blk->elemSize >= size); // ptr might be from a larger block in case _Realloc() failed to shrink
|
||||
blk->freeElem((unsigned char*)ptr);
|
||||
if(blk->freeElems == blk->maxElems)
|
||||
_FreeBlock(blk); // remove if completely unused
|
||||
return;
|
||||
}
|
||||
}
|
||||
_FallbackFree(ptr);
|
||||
}
|
||||
|
||||
void *SmallBlockAllocator::_Realloc(void *ptr, unsigned int newsize, unsigned int oldsize)
|
||||
{
|
||||
void *newptr = _Alloc(newsize);
|
||||
|
||||
// If the new allocation failed, just re-use the old pointer if it was a shrink request
|
||||
// This also satisfies Lua, which assumes that realloc() shrink requests cannot fail
|
||||
if(!newptr)
|
||||
return newsize <= oldsize ? ptr : NULL;
|
||||
|
||||
memcpy(newptr, ptr, std::min(oldsize, newsize));
|
||||
_Free(ptr, oldsize);
|
||||
return newptr;
|
||||
}
|
||||
|
100
BBGE/MemoryAllocatorSmallBlock.h
Normal file
100
BBGE/MemoryAllocatorSmallBlock.h
Normal file
|
@ -0,0 +1,100 @@
|
|||
#ifndef MEMORY_ALLOCATOR_SMALL_BLOCK_H
|
||||
#define MEMORY_ALLOCATOR_SMALL_BLOCK_H
|
||||
|
||||
/* Optimized memory allocator for small & frequent (de-)allocations.
|
||||
* Low memory overhead. Used for Lua.
|
||||
* Inspired by http://dns.achurch.org/cgi-bin/hg/aquaria-psp/file/tip/PSP/src/lalloc.c
|
||||
*/
|
||||
|
||||
// Originally made for LV3proj_ng (https://github.com/fgenesis/lv3proj_ng)
|
||||
// Hacked in shape for use in Aquaria
|
||||
// Public domain
|
||||
|
||||
|
||||
#include <vector>
|
||||
|
||||
class SmallBlockAllocator
|
||||
{
|
||||
public:
|
||||
|
||||
SmallBlockAllocator(unsigned int blockSizeMin, unsigned int blockSizeMax, unsigned int blockSizeIncr = 8,
|
||||
unsigned int elemsPerBlockMin = 64, unsigned int elemsPerBlockMax = 2048);
|
||||
|
||||
~SmallBlockAllocator();
|
||||
|
||||
void *Alloc(void *ptr, size_t newsize, size_t oldsize);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void *_Alloc(unsigned int size);
|
||||
void *_Realloc(void *ptr, unsigned int newsize, unsigned int oldsize);
|
||||
void _Free(void* ptr, unsigned int size);
|
||||
|
||||
void *_FallbackAlloc(unsigned int size);
|
||||
void _FallbackFree(void *ptr);
|
||||
|
||||
struct Block
|
||||
{
|
||||
// block header start
|
||||
Block *next;
|
||||
Block *prev;
|
||||
unsigned short maxElems;
|
||||
unsigned short freeElems;
|
||||
unsigned short elemSize;
|
||||
unsigned short bitmapInts;
|
||||
// block header end
|
||||
|
||||
unsigned int bitmap[1]; // variable sized
|
||||
// actual storage memory starts after bitmap[bitmapInts]
|
||||
|
||||
inline unsigned char *getPtr()
|
||||
{
|
||||
return (unsigned char*)&bitmap[bitmapInts];
|
||||
}
|
||||
inline const unsigned char *getPtr() const
|
||||
{
|
||||
return (unsigned char*)&bitmap[bitmapInts];
|
||||
}
|
||||
inline unsigned char *getEndPtr()
|
||||
{
|
||||
return getPtr() + (maxElems * elemSize);
|
||||
}
|
||||
inline const unsigned char *getEndPtr() const
|
||||
{
|
||||
return getPtr() + (maxElems * elemSize);
|
||||
}
|
||||
|
||||
void *allocElem();
|
||||
void freeElem(unsigned char *ptr);
|
||||
bool contains(unsigned char *ptr) const;
|
||||
};
|
||||
|
||||
Block *_AllocBlock(unsigned int elemCount, unsigned int elemSize);
|
||||
void _FreeBlock(Block *blk);
|
||||
Block *_AppendBlock(unsigned int elemSize);
|
||||
Block *_GetFreeBlock(unsigned int elemSize); // NULL if none free
|
||||
|
||||
Block *_FindBlockContainingPtr(void *ptr);
|
||||
|
||||
inline unsigned int GetIndexForElemSize(unsigned int elemSize)
|
||||
{
|
||||
//ASSERT(elemSize);
|
||||
//ASSERT(elemSize <= _blockSizeMax);
|
||||
return ((elemSize + (_blockSizeIncr - 1)) / _blockSizeIncr) - 1;
|
||||
}
|
||||
|
||||
static bool Block_ptr_cmp(const Block *blk, const void *ptr);
|
||||
|
||||
Block **_blocks;
|
||||
std::vector<Block*> _allblocks; // always sorted by pointer address
|
||||
|
||||
unsigned int _blockSizeMin;
|
||||
unsigned int _blockSizeMax;
|
||||
unsigned int _blockSizeIncr;
|
||||
|
||||
unsigned int _elemsPerBlockMin;
|
||||
unsigned int _elemsPerBlockMax;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
ParticleEffect::ParticleEffect() : RenderObject()
|
||||
{
|
||||
addType(SCO_PARTICLE_EFFECT);
|
||||
running = false;
|
||||
waitForParticles = true;
|
||||
effectLife = -1;
|
||||
|
|
|
@ -39,6 +39,7 @@ static const char *scriptObjTypeNames[] =
|
|||
/* (1 <<11) */ "Text",
|
||||
/* (1 <<12) */ "PauseQuad",
|
||||
/* (1 <<13) */ "Shader",
|
||||
/* (1 <<14) */ "ParticleEffect",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ enum ScriptObjectType
|
|||
SCO_TEXT = 0x0800,
|
||||
SCO_PAUSEQUAD = 0x1000,
|
||||
SCO_SHADER = 0x2000,
|
||||
SCO_PARTICLE_EFFECT = 0x4000,
|
||||
|
||||
SCO_FORCE_32BIT = 0xFFFFFFFF
|
||||
};
|
||||
|
|
|
@ -164,7 +164,10 @@ bool Shader::isLoaded() const
|
|||
|
||||
void Shader::reload()
|
||||
{
|
||||
load(vertFile, fragFile);
|
||||
if (vertFile.size() || fragFile.size())
|
||||
load(vertFile, fragFile);
|
||||
else
|
||||
loadSrc(vertSrc.c_str(), fragSrc.c_str());
|
||||
}
|
||||
|
||||
void Shader::bind()
|
||||
|
@ -321,6 +324,9 @@ void Shader::loadSrc(const char *vertCode, const char *fragCode)
|
|||
return;
|
||||
}
|
||||
|
||||
vertSrc = vertCode ? vertCode : "";
|
||||
fragSrc = fragCode ? fragCode : "";
|
||||
|
||||
_queryUniforms();
|
||||
|
||||
#endif
|
||||
|
@ -328,15 +334,6 @@ void Shader::loadSrc(const char *vertCode, const char *fragCode)
|
|||
|
||||
void Shader::_setUniform(Uniform *u)
|
||||
{
|
||||
/*if(u->location == -1)
|
||||
{
|
||||
u->location = glGetUniformLocationARB(g_programObj, u->name);
|
||||
if(u->location == -1)
|
||||
{
|
||||
u->dirty = false;
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
switch(u->type)
|
||||
{
|
||||
case GL_FLOAT: glUniform1fvARB(u->location, 1, u->data.f); break;
|
||||
|
@ -381,9 +378,13 @@ void Shader::_queryUniforms()
|
|||
glGetObjectParameterivARB(g_programObj, GL_OBJECT_ACTIVE_UNIFORMS_ARB , &numUniforms);
|
||||
|
||||
if (numUniforms <= 0)
|
||||
{
|
||||
uniforms.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
uniforms.reserve(numUniforms);
|
||||
size_t total = 0;
|
||||
|
||||
for (unsigned int i = 0; i < numUniforms; ++i)
|
||||
{
|
||||
|
@ -396,15 +397,27 @@ void Shader::_queryUniforms()
|
|||
u.location = glGetUniformLocationARB(g_programObj, u.name);
|
||||
if(u.location == -1)
|
||||
continue;
|
||||
u.dirty = false;
|
||||
u.type = type;
|
||||
memset(&u.data, 0, sizeof(u.data));
|
||||
|
||||
uniforms.push_back(u);
|
||||
bool add = total >= uniforms.size();
|
||||
if(add || type != u.type) // keep data intact on reload
|
||||
memset(&u.data, 0, sizeof(u.data));
|
||||
u.dirty = true;
|
||||
u.type = type;
|
||||
|
||||
if(add)
|
||||
uniforms.push_back(u);
|
||||
else
|
||||
uniforms[total] = u;
|
||||
|
||||
++total;
|
||||
}
|
||||
|
||||
uniforms.resize(total);
|
||||
|
||||
// sort to be able to do binary search later
|
||||
std::sort(uniforms.begin(), uniforms.end());
|
||||
|
||||
uniformsDirty = true;
|
||||
}
|
||||
|
||||
int Shader::_getUniformIndex(const char *name)
|
||||
|
|
|
@ -44,6 +44,7 @@ public:
|
|||
|
||||
protected:
|
||||
std::string vertFile, fragFile;
|
||||
std::string vertSrc, fragSrc;
|
||||
#ifdef BBGE_BUILD_OPENGL
|
||||
GLuint g_programObj;
|
||||
int numUniforms;
|
||||
|
@ -72,7 +73,7 @@ private:
|
|||
float f[4];
|
||||
};
|
||||
} data;
|
||||
char name[32];
|
||||
char name[64];
|
||||
|
||||
bool operator< (const Uniform&) const;
|
||||
};
|
||||
|
|
|
@ -251,6 +251,7 @@ public:
|
|||
void selectNextBone();
|
||||
|
||||
bool isLoaded();
|
||||
int getNumAnimLayers() const { return animLayers.size(); }
|
||||
|
||||
AnimationLayer* getAnimationLayer(int l);
|
||||
int getBoneIdx(Bone *b);
|
||||
|
|
84
BBGE/bithacks.h
Normal file
84
BBGE/bithacks.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
#ifndef BITHACKS_H
|
||||
#define BITHACKS_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <intrin.h>
|
||||
#endif
|
||||
|
||||
namespace bithacks {
|
||||
|
||||
typedef unsigned int uint32;
|
||||
typedef int int32;
|
||||
|
||||
// floor to next power of 2
|
||||
inline uint32 flp2(uint32 x)
|
||||
{
|
||||
x |= (x >> 1);
|
||||
x |= (x >> 2);
|
||||
x |= (x >> 4);
|
||||
x |= (x >> 8);
|
||||
x |= (x >> 16);
|
||||
return x - (x >> 1);
|
||||
}
|
||||
|
||||
// ceil to next power of 2
|
||||
inline uint32 clp2(uint32 x)
|
||||
{
|
||||
--x;
|
||||
x |= (x >> 1);
|
||||
x |= (x >> 2);
|
||||
x |= (x >> 4);
|
||||
x |= (x >> 8);
|
||||
x |= (x >> 16);
|
||||
return x + 1;
|
||||
}
|
||||
|
||||
inline uint32 popcnt(uint32 x)
|
||||
{
|
||||
x -= ((x >> 1) & 0x55555555);
|
||||
x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
|
||||
x = (((x >> 4) + x) & 0x0f0f0f0f);
|
||||
x += (x >> 8);
|
||||
x += (x >> 16);
|
||||
return x & 0x0000003f;
|
||||
}
|
||||
|
||||
inline uint32 ctz(uint32 x)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
return __builtin_ctz(x);
|
||||
#elif defined(_MSC_VER) && defined(_M_IX86)
|
||||
unsigned long r = 0;
|
||||
_BitScanForward(&r, x);
|
||||
return r;
|
||||
#else
|
||||
return popcnt((x & -x) - 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline unsigned int clz(uint32 x)
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
return __builtin_clz(x);
|
||||
#elif defined(_MSC_VER) && defined(_M_IX86)
|
||||
unsigned long r = 0;
|
||||
_BitScanReverse(&r, x);
|
||||
return r;
|
||||
#else
|
||||
x |= (x >> 1);
|
||||
x |= (x >> 2);
|
||||
x |= (x >> 4);
|
||||
x |= (x >> 8);
|
||||
x |= (x >> 16);
|
||||
return 32 - popcnt(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}; // end namespace bithacks
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue