1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-06-24 21:39:35 +00:00

Code refactor: add abstract class UniformCollection.

Implement it for desktop GL: OGL3X/UniformBlock
and for GLES2: GLES2/UniformSet

GLES3 and above must use OGL3X/UniformBlock.
This commit is contained in:
Sergey Lipskiy 2015-05-20 11:32:05 +06:00
parent ed4271e60e
commit e73cee3a58
12 changed files with 622 additions and 579 deletions

View File

@ -287,6 +287,7 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\N64.cpp" />
<ClCompile Include="..\..\src\OGL3X\UniformBlock.cpp" />
<ClCompile Include="..\..\src\OpenGL.cpp" />
<ClCompile Include="..\..\src\PostProcessor.cpp" />
<ClCompile Include="..\..\src\RDP.CPP" />
@ -358,6 +359,7 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="..\..\src\N64.h" />
<ClInclude Include="..\..\src\OGL3X\UniformBlock.h" />
<ClInclude Include="..\..\src\OpenGL.h" />
<ClInclude Include="..\..\src\PluginAPI.h" />
<ClInclude Include="..\..\src\PostProcessor.h" />
@ -368,6 +370,7 @@
<ClInclude Include="..\..\src\Textures.h" />
<ClInclude Include="..\..\src\Turbo3D.h" />
<ClInclude Include="..\..\src\Types.h" />
<ClInclude Include="..\..\src\UniformCollection.h" />
<ClInclude Include="..\..\src\VI.h" />
<ClInclude Include="..\..\src\F3D.h" />
<ClInclude Include="..\..\src\F3DDKR.h" />

View File

@ -36,6 +36,12 @@
<Filter Include="Source Files\mupenplus">
<UniqueIdentifier>{b10a85f0-0fbb-4f8e-b6d8-78ee2a6394bf}</UniqueIdentifier>
</Filter>
<Filter Include="OGL3X">
<UniqueIdentifier>{b3016e90-1a88-4a28-9ca4-fbebf41e10ee}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\OGL3X">
<UniqueIdentifier>{32bbb389-ea50-4ac9-bb55-84e4f066fe94}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\Combiner.cpp">
@ -188,6 +194,9 @@
<ClCompile Include="..\..\src\windows\GLFunctions_windows.cpp">
<Filter>Source Files\windows</Filter>
</ClCompile>
<ClCompile Include="..\..\src\OGL3X\UniformBlock.cpp">
<Filter>Source Files\OGL3X</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\3DMath.h">
@ -331,5 +340,11 @@
<ClInclude Include="..\..\src\Keys.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\UniformCollection.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\OGL3X\UniformBlock.h">
<Filter>OGL3X</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -41,6 +41,7 @@ set(GLideN64_SOURCES
PostProcessor.cpp
VI.cpp
common/CommonAPIImpl_common.cpp
OGL3X/UniformBlock.cpp
)
if(MUPENPLUSAPI)

View File

@ -1,6 +1,7 @@
#include "OpenGL.h"
#include "Combiner.h"
#include "GLSLCombiner.h"
#include "UniformCollection.h"
#include "Debug.h"
#include "gDP.h"
@ -85,13 +86,13 @@ CombinerInfo & CombinerInfo::get()
void CombinerInfo::init()
{
m_pCurrent = NULL;
m_pUniformBlock = new UniformBlock;
m_pUniformCollection = createUniformCollection();
}
void CombinerInfo::destroy()
{
delete m_pUniformBlock;
m_pUniformBlock = NULL;
delete m_pUniformCollection;
m_pUniformCollection = NULL;
m_pCurrent = NULL;
for (Combiners::iterator cur = m_combiners.begin(); cur != m_combiners.end(); ++cur)
delete cur->second;
@ -237,7 +238,7 @@ void CombinerInfo::setCombine(u64 _mux )
} else {
m_pCurrent = _compile(_mux);
m_pCurrent->update(true);
m_pUniformBlock->bindWithShaderCombiner(m_pCurrent);
m_pUniformCollection->bindWithShaderCombiner(m_pCurrent);
m_combiners[_mux] = m_pCurrent;
}
m_bChanged = true;
@ -245,57 +246,57 @@ void CombinerInfo::setCombine(u64 _mux )
void CombinerInfo::updatePrimColor()
{
if (m_pUniformBlock != NULL)
m_pUniformBlock->setColorData(UniformBlock::cuPrimColor, sizeof(f32)* 5, &gDP.primColor.r);
if (m_pUniformCollection != NULL)
m_pUniformCollection->setColorData(UniformCollection::cuPrimColor, sizeof(f32)* 5, &gDP.primColor.r);
}
void CombinerInfo::updateEnvColor()
{
if (m_pUniformBlock != NULL)
m_pUniformBlock->setColorData(UniformBlock::cuEnvColor, sizeof(f32)* 4, &gDP.envColor.r);
if (m_pUniformCollection != NULL)
m_pUniformCollection->setColorData(UniformCollection::cuEnvColor, sizeof(f32)* 4, &gDP.envColor.r);
}
void CombinerInfo::updateFogColor()
{
if (m_pUniformBlock != NULL)
m_pUniformBlock->setColorData(UniformBlock::cuFogColor, sizeof(f32)* 4, &gDP.fogColor.r);
if (m_pUniformCollection != NULL)
m_pUniformCollection->setColorData(UniformCollection::cuFogColor, sizeof(f32)* 4, &gDP.fogColor.r);
}
void CombinerInfo::updateBlendColor()
{
if (m_pUniformBlock != NULL)
m_pUniformBlock->setColorData(UniformBlock::cuBlendColor, sizeof(f32)* 4, &gDP.blendColor.r);
if (m_pUniformCollection != NULL)
m_pUniformCollection->setColorData(UniformCollection::cuBlendColor, sizeof(f32)* 4, &gDP.blendColor.r);
}
void CombinerInfo::updateKeyColor()
{
if (m_pUniformBlock != NULL)
m_pUniformBlock->setColorData(UniformBlock::cuCenterColor, sizeof(f32)* 8, &gDP.key.center.r);
if (m_pUniformCollection != NULL)
m_pUniformCollection->setColorData(UniformCollection::cuCenterColor, sizeof(f32)* 8, &gDP.key.center.r);
}
void CombinerInfo::updateConvertColor()
{
if (m_pUniformBlock == NULL)
if (m_pUniformCollection == NULL)
return;
f32 convert[2] = { gDP.convert.k4*0.0039215689f, gDP.convert.k5*0.0039215689f };
m_pUniformBlock->setColorData(UniformBlock::cuK4, sizeof(convert), convert);
m_pUniformCollection->setColorData(UniformCollection::cuK4, sizeof(convert), convert);
}
void CombinerInfo::updateTextureParameters()
{
if (m_pUniformBlock != NULL)
m_pUniformBlock->updateTextureParameters();
if (m_pUniformCollection != NULL)
m_pUniformCollection->updateTextureParameters();
}
void CombinerInfo::updateLightParameters()
{
if (m_pUniformBlock != NULL)
m_pUniformBlock->updateLightParameters();
if (m_pUniformCollection != NULL)
m_pUniformCollection->updateLightParameters();
gSP.changed &= ~CHANGED_LIGHT;
}
void CombinerInfo::updateParameters()
{
if (m_pUniformBlock != NULL)
m_pUniformBlock->updateUniforms(m_pCurrent);
if (m_pUniformCollection != NULL)
m_pUniformCollection->updateUniforms(m_pCurrent);
}

View File

@ -114,7 +114,7 @@ struct CombineCycle
};
class ShaderCombiner;
class UniformBlock;
class UniformCollection;
class CombinerInfo
{
public:
@ -150,7 +150,7 @@ private:
ShaderCombiner * m_pCurrent;
typedef std::map<u64, ShaderCombiner *> Combiners;
Combiners m_combiners;
UniformBlock * m_pUniformBlock;
UniformCollection * m_pUniformCollection;
};
inline

138
src/GLES2/UniformSet.cpp Normal file
View File

@ -0,0 +1,138 @@
#include "UniformSet.h"
#include "../Config.h"
#include "../Textures.h"
#define LocateUniform2(A) \
location.A.loc = glGetUniformLocation(program, #A);
void UniformSet::bindWithShaderCombiner(ShaderCombiner * _pCombiner)
{
const u64 mux = _pCombiner->getMux();
const GLuint program = _pCombiner->m_program;
m_uniforms.emplace(mux, program);
UniformSetLocation & location = m_uniforms.at(mux);
// Texture parameters
if (_pCombiner->usesTexture()) {
LocateUniform2(uTexScale);
LocateUniform2(uTexMask[0]);
LocateUniform2(uTexMask[1]);
LocateUniform2(uTexOffset[0]);
LocateUniform2(uTexOffset[1]);
LocateUniform2(uCacheScale[0]);
LocateUniform2(uCacheScale[1]);
LocateUniform2(uCacheOffset[0]);
LocateUniform2(uCacheOffset[1]);
LocateUniform2(uCacheShiftScale[0]);
LocateUniform2(uCacheShiftScale[1]);
LocateUniform2(uCacheFrameBuffer);
LocateUniform2(uTextureSize[0]);
LocateUniform2(uTextureSize[1]);
_updateTextureUniforms(location, _pCombiner->usesTile(0), _pCombiner->usesTile(1), true);
}
// Colors
LocateUniform2(uFogColor);
LocateUniform2(uCenterColor);
LocateUniform2(uScaleColor);
LocateUniform2(uBlendColor);
LocateUniform2(uEnvColor);
LocateUniform2(uPrimColor);
LocateUniform2(uPrimLod);
LocateUniform2(uK4);
LocateUniform2(uK5);
_updateColorUniforms(location, true);
// Lights
if (config.generalEmulation.enableHWLighting != 0 && GBI.isHWLSupported() && _pCombiner->usesShadeColor()) {
// locate lights uniforms
char buf[32];
for (s32 i = 0; i < 8; ++i) {
sprintf(buf, "uLightDirection[%d]", i);
location.uLightDirection[i].loc = glGetUniformLocation(program, buf);
sprintf(buf, "uLightColor[%d]", i);
location.uLightColor[i].loc = glGetUniformLocation(program, buf);
}
_updateLightUniforms(location, true);
}
}
void UniformSet::_updateColorUniforms(UniformSetLocation & _location, bool _bForce)
{
_location.uFogColor.set(&gDP.fogColor.r, _bForce);
_location.uCenterColor.set(&gDP.key.center.r, _bForce);
_location.uScaleColor.set(&gDP.key.scale.r, _bForce);
_location.uBlendColor.set(&gDP.blendColor.r, _bForce);
_location.uEnvColor.set(&gDP.envColor.r, _bForce);
_location.uPrimColor.set(&gDP.primColor.r, _bForce);
_location.uPrimLod.set(gDP.primColor.l, _bForce);
_location.uK4.set(gDP.convert.k4*0.0039215689f, _bForce);
_location.uK5.set(gDP.convert.k5*0.0039215689f, _bForce);
}
void UniformSet::_updateTextureUniforms(UniformSetLocation & _location, bool _bUsesT0, bool _bUsesT1, bool _bForce)
{
int nFB[2] = { 0, 0 };
const bool bUsesTile[2] = { _bUsesT0, _bUsesT1 };
TextureCache & cache = textureCache();
for (u32 t = 0; t < 2; ++t) {
if (!bUsesTile[t])
continue;
if (gSP.textureTile[t] != NULL) {
if (gSP.textureTile[t]->textureMode == TEXTUREMODE_BGIMAGE || gSP.textureTile[t]->textureMode == TEXTUREMODE_FRAMEBUFFER_BG) {
_location.uTexOffset[t].set(0.0f, 0.0f, _bForce);
_location.uTexMask[t].set(0.0f, 0.0f, _bForce);
}
else {
_location.uTexOffset[t].set(gSP.textureTile[t]->fuls, gSP.textureTile[t]->fult, _bForce);
_location.uTexMask[t].set(
gSP.textureTile[t]->masks > 0 ? (float)(1 << gSP.textureTile[t]->masks) : 0.0f,
gSP.textureTile[t]->maskt > 0 ? (float)(1 << gSP.textureTile[t]->maskt) : 0.0f,
_bForce);
}
}
if (cache.current[t] != NULL) {
f32 shiftScaleS = 1.0f;
f32 shiftScaleT = 1.0f;
getTextureShiftScale(t, cache, shiftScaleS, shiftScaleT);
_location.uCacheShiftScale[t].set(shiftScaleS, shiftScaleT, _bForce);
_location.uCacheScale[t].set(cache.current[t]->scaleS, cache.current[t]->scaleT, _bForce);
_location.uCacheOffset[t].set(cache.current[t]->offsetS, cache.current[t]->offsetT, _bForce);
_location.uTextureSize[t].set(cache.current[t]->realWidth, cache.current[t]->realHeight, _bForce);
nFB[t] = cache.current[t]->frameBufferTexture;
}
}
_location.uCacheFrameBuffer.set(nFB[0], nFB[1], _bForce);
_location.uTexScale.set(gSP.texture.scales, gSP.texture.scalet, _bForce);
}
void UniformSet::_updateLightUniforms(UniformSetLocation & _location, bool _bForce)
{
for (s32 i = 0; i <= gSP.numLights; ++i) {
_location.uLightDirection[i].set(&gSP.lights[i].x, _bForce);
_location.uLightColor[i].set(&gSP.lights[i].r, _bForce);
}
}
void UniformSet::updateUniforms(ShaderCombiner * _pCombiner)
{
UniformSetLocation & location = m_uniforms.at(_pCombiner->getMux());
_updateColorUniforms(location, false);
OGLRender::RENDER_STATE rs = video().getRender().getRenderState();
if ((rs == OGLRender::rsTriangle || rs == OGLRender::rsLine) && _pCombiner->usesTexture())
_updateTextureUniforms(location, _pCombiner->usesTile(0), _pCombiner->usesTile(1), false);
if (config.generalEmulation.enableHWLighting != 0 && GBI.isHWLSupported() && _pCombiner->usesShadeColor())
_updateLightUniforms(location, false);
}
UniformCollection * createUniformCollection()
{
return new UniformSet();
}

70
src/GLES2/UniformSet.h Normal file
View File

@ -0,0 +1,70 @@
#ifndef UNIFORM_SET_H
#define UNIFORM_SET_H
#include "../UniformCollection.h"
class UniformSet : public UniformCollection
{
public:
UniformSet() {}
~UniformSet() {}
virtual void bindWithShaderCombiner(ShaderCombiner * _pCombiner);
virtual void setColorData(ColorUniforms _index, u32 _dataSize, const void * _data) {}
virtual void updateTextureParameters() {}
virtual void updateLightParameters() {}
virtual void updateUniforms(ShaderCombiner * _pCombiner);
private:
struct fv3Uniform {
GLint loc;
float val[3];
void set(float * _pVal, bool _force) {
const size_t szData = sizeof(float)* 3;
if (loc >= 0 && (_force || memcmp(val, _pVal, szData) != 0)) {
memcpy(val, _pVal, szData);
glUniform3fv(loc, 1, _pVal);
}
}
};
struct fv4Uniform {
GLint loc;
float val[4];
void set(float * _pVal, bool _force) {
const size_t szData = sizeof(float)* 4;
if (loc >= 0 && (_force || memcmp(val, _pVal, szData) != 0)) {
memcpy(val, _pVal, szData);
glUniform4fv(loc, 1, _pVal);
}
}
};
struct UniformSetLocation
{
UniformSetLocation(GLuint _program) : m_program(_program) {}
GLuint m_program;
// Texture parameters
ShaderCombiner::fv2Uniform uTexScale, uTexMask[2], uTexOffset[2], uCacheScale[2], uCacheOffset[2], uCacheShiftScale[2];
ShaderCombiner::iv2Uniform uCacheFrameBuffer, uTextureSize[2];
// Colors
fv4Uniform uFogColor, uCenterColor, uScaleColor, uBlendColor, uEnvColor, uPrimColor;
ShaderCombiner::fUniform uPrimLod, uK4, uK5;
// Lights
fv3Uniform uLightDirection[8], uLightColor[8];
};
void _updateColorUniforms(UniformSetLocation & _location, bool _bForce);
void _updateTextureUniforms(UniformSetLocation & _location, bool _bUsesT0, bool _bUsesT1, bool _bForce);
void _updateLightUniforms(UniformSetLocation & _location, bool _bForce);
typedef std::map<u64, UniformSetLocation> Uniforms;
Uniforms m_uniforms;
};
#endif // UNIFORM_SET_H

View File

@ -1016,379 +1016,3 @@ void SetMonochromeCombiner() {
glUseProgram(g_monochrome_image_program);
gDP.changed |= CHANGED_COMBINE;
}
/*======================UniformBlock==========================*/
#ifdef GL_UNIFORMBLOCK_SUPPORT
static
const char * strTextureUniforms[UniformBlock::tuTotal] = {
"uTexScale",
"uTexMask",
"uTexOffset",
"uCacheScale",
"uCacheOffset",
"uCacheShiftScale",
"uCacheFrameBuffer"
};
static
const char * strColorUniforms[UniformBlock::cuTotal] = {
"uFogColor",
"uCenterColor",
"uScaleColor",
"uBlendColor",
"uEnvColor",
"uPrimColor",
"uPrimLod",
"uK4",
"uK5"
};
static
const char * strLightUniforms[UniformBlock::luTotal] = {
"uLightDirection",
"uLightColor"
};
UniformBlock::UniformBlock() : m_currentBuffer(0)
{
}
UniformBlock::~UniformBlock()
{
}
void UniformBlock::_initTextureBuffer(GLuint _program)
{
const GLint blockSize = m_textureBlock.initBuffer(_program, "TextureBlock", strTextureUniforms);
if (blockSize == 0)
return;
m_textureBlockData.resize(blockSize);
GLbyte * pData = m_textureBlockData.data();
memset(pData, 0, blockSize);
glBindBuffer(GL_UNIFORM_BUFFER, m_textureBlock.m_buffer);
glBufferData(GL_UNIFORM_BUFFER, blockSize, 0, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, m_textureBlock.m_blockBindingPoint, m_textureBlock.m_buffer);
updateTextureParameters();
}
void UniformBlock::_initColorsBuffer(GLuint _program)
{
const GLint blockSize = m_colorsBlock.initBuffer(_program, "ColorsBlock", strColorUniforms);
if (blockSize == 0)
return;
m_colorsBlockData.resize(blockSize);
GLbyte * pData = m_colorsBlockData.data();
memset(pData, 0, blockSize);
memcpy(pData + m_colorsBlock.m_offsets[cuFogColor], &gDP.fogColor.r, sizeof(f32)* 4);
memcpy(pData + m_colorsBlock.m_offsets[cuCenterColor], &gDP.key.center.r, sizeof(f32)* 4);
memcpy(pData + m_colorsBlock.m_offsets[cuScaleColor], &gDP.key.scale.r, sizeof(f32)* 4);
memcpy(pData + m_colorsBlock.m_offsets[cuEnvColor], &gDP.envColor.r, sizeof(f32)* 4);
memcpy(pData + m_colorsBlock.m_offsets[cuPrimColor], &gDP.primColor.r, sizeof(f32)* 4);
*(f32*)(pData + m_colorsBlock.m_offsets[cuPrimLod]) = gDP.primColor.l;
*(f32*)(pData + m_colorsBlock.m_offsets[cuK4]) = gDP.convert.k4*0.0039215689f;
*(f32*)(pData + m_colorsBlock.m_offsets[cuK5]) = gDP.convert.k5*0.0039215689f;
glBindBuffer(GL_UNIFORM_BUFFER, m_colorsBlock.m_buffer);
glBufferData(GL_UNIFORM_BUFFER, blockSize, pData, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, m_colorsBlock.m_blockBindingPoint, m_colorsBlock.m_buffer);
m_currentBuffer = m_colorsBlock.m_buffer;
}
void UniformBlock::_initLightBuffer(GLuint _program)
{
const GLint blockSize = m_lightBlock.initBuffer(_program, "LightBlock", strLightUniforms);
if (blockSize == 0)
return;
m_lightBlockData.resize(blockSize);
GLbyte * pData = m_lightBlockData.data();
memset(pData, 0, blockSize);
glBindBuffer(GL_UNIFORM_BUFFER, m_lightBlock.m_buffer);
glBufferData(GL_UNIFORM_BUFFER, blockSize, 0, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, m_lightBlock.m_blockBindingPoint, m_lightBlock.m_buffer);
updateLightParameters();
}
bool UniformBlock::_isDataChanged(void * _pBuffer, const void * _pData, u32 _dataSize)
{
u32 * pSrc = (u32*)_pData;
u32 * pDst = (u32*)_pBuffer;
u32 cnt = _dataSize / 4;
for (u32 i = 0; i < cnt; ++i) {
if (pSrc[i] != pDst[i]) {
memcpy(_pBuffer, _pData, _dataSize);
return true;
}
}
return false;
}
void UniformBlock::bindWithShaderCombiner(ShaderCombiner * _pCombiner)
{
const GLuint program = _pCombiner->m_program;
if (_pCombiner->usesTexture()) {
if (m_textureBlock.m_buffer == 0)
_initTextureBuffer(program);
else {
const GLint blockIndex = glGetUniformBlockIndex(program, "TextureBlock");
if (blockIndex != GL_INVALID_INDEX)
glUniformBlockBinding(program, blockIndex, m_textureBlock.m_blockBindingPoint);
}
}
if (m_colorsBlock.m_buffer == 0)
_initColorsBuffer(program);
else {
const GLint blockIndex = glGetUniformBlockIndex(program, "ColorsBlock");
if (blockIndex != GL_INVALID_INDEX)
glUniformBlockBinding(program, blockIndex, m_colorsBlock.m_blockBindingPoint);
}
if (_pCombiner->usesShadeColor() && config.generalEmulation.enableHWLighting != 0) {
if (m_lightBlock.m_buffer == 0)
_initLightBuffer(program);
else {
const GLint blockIndex = glGetUniformBlockIndex(program, "LightBlock");
if (blockIndex != GL_INVALID_INDEX)
glUniformBlockBinding(program, blockIndex, m_lightBlock.m_blockBindingPoint);
}
}
}
void UniformBlock::setColorData(ColorUniforms _index, u32 _dataSize, const void * _data)
{
if (m_colorsBlock.m_buffer == 0)
return;
if (!_isDataChanged(m_colorsBlockData.data() + m_colorsBlock.m_offsets[_index], _data, _dataSize))
return;
if (m_currentBuffer != m_colorsBlock.m_buffer) {
m_currentBuffer = m_colorsBlock.m_buffer;
glBindBuffer(GL_UNIFORM_BUFFER, m_colorsBlock.m_buffer);
}
glBufferSubData(GL_UNIFORM_BUFFER, m_colorsBlock.m_offsets[_index], _dataSize, _data);
}
void UniformBlock::updateTextureParameters()
{
if (m_textureBlock.m_buffer == 0)
return;
GLbyte * pData = m_textureBlockData.data();
f32 texScale[4] = { gSP.texture.scales, gSP.texture.scalet, 0, 0 };
memcpy(pData + m_textureBlock.m_offsets[tuTexScale], texScale, m_textureBlock.m_offsets[tuTexMask] - m_textureBlock.m_offsets[tuTexScale]);
f32 texOffset[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
f32 texMask[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
if (gSP.textureTile[0] != NULL) {
if (gSP.textureTile[0]->textureMode != TEXTUREMODE_BGIMAGE && gSP.textureTile[0]->textureMode != TEXTUREMODE_FRAMEBUFFER_BG) {
texOffset[0] = gSP.textureTile[0]->fuls;
texOffset[1] = gSP.textureTile[0]->fult;
texMask[0] = gSP.textureTile[0]->masks > 0 ? (float)(1 << gSP.textureTile[0]->masks) : 0.0f;
texMask[1] = gSP.textureTile[0]->maskt > 0 ? (float)(1 << gSP.textureTile[0]->maskt) : 0.0f;
}
}
if (gSP.textureTile[1] != 0) {
texOffset[4] = gSP.textureTile[1]->fuls;
texOffset[5] = gSP.textureTile[1]->fult;
texMask[4] = gSP.textureTile[1]->masks > 0 ? (float)(1 << gSP.textureTile[1]->masks) : 0.0f;
texMask[5] = gSP.textureTile[1]->maskt > 0 ? (float)(1 << gSP.textureTile[1]->maskt) : 0.0f;
}
memcpy(pData + m_textureBlock.m_offsets[tuTexMask], texMask, m_textureBlock.m_offsets[tuTexOffset] - m_textureBlock.m_offsets[tuTexMask]);
memcpy(pData + m_textureBlock.m_offsets[tuTexOffset], texOffset, m_textureBlock.m_offsets[tuCacheScale] - m_textureBlock.m_offsets[tuTexOffset]);
f32 texCacheScale[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
f32 texCacheOffset[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
f32 texCacheShiftScale[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
GLint texCacheFrameBuffer[4] = { 0, 0, 0, 0 };
TextureCache & cache = textureCache();
if (cache.current[0]) {
texCacheScale[0] = cache.current[0]->scaleS;
texCacheScale[1] = cache.current[0]->scaleT;
texCacheOffset[0] = cache.current[0]->offsetS;
texCacheOffset[1] = cache.current[0]->offsetT;
f32 shiftScaleS = 1.0f;
f32 shiftScaleT = 1.0f;
getTextureShiftScale(0, cache, shiftScaleS, shiftScaleT);
texCacheShiftScale[0] = shiftScaleS;
texCacheShiftScale[1] = shiftScaleT;
texCacheFrameBuffer[0] = cache.current[0]->frameBufferTexture;
}
if (cache.current[1]) {
texCacheScale[4] = cache.current[1]->scaleS;
texCacheScale[5] = cache.current[1]->scaleT;
texCacheOffset[4] = cache.current[1]->offsetS;
texCacheOffset[5] = cache.current[1]->offsetT;
f32 shiftScaleS = 1.0f;
f32 shiftScaleT = 1.0f;
getTextureShiftScale(1, cache, shiftScaleS, shiftScaleT);
texCacheShiftScale[4] = shiftScaleS;
texCacheShiftScale[5] = shiftScaleT;
texCacheFrameBuffer[1] = cache.current[1]->frameBufferTexture;
}
memcpy(pData + m_textureBlock.m_offsets[tuCacheScale], texCacheScale, m_textureBlock.m_offsets[tuCacheOffset] - m_textureBlock.m_offsets[tuCacheScale]);
memcpy(pData + m_textureBlock.m_offsets[tuCacheOffset], texCacheOffset, m_textureBlock.m_offsets[tuCacheShiftScale] - m_textureBlock.m_offsets[tuCacheOffset]);
memcpy(pData + m_textureBlock.m_offsets[tuCacheShiftScale], texCacheShiftScale, m_textureBlock.m_offsets[tuCacheFrameBuffer] - m_textureBlock.m_offsets[tuCacheShiftScale]);
memcpy(pData + m_textureBlock.m_offsets[tuCacheFrameBuffer], texCacheFrameBuffer, m_textureBlockData.size() - m_textureBlock.m_offsets[tuCacheFrameBuffer]);
if (m_currentBuffer != m_textureBlock.m_buffer) {
m_currentBuffer = m_textureBlock.m_buffer;
glBindBuffer(GL_UNIFORM_BUFFER, m_textureBlock.m_buffer);
}
glBufferSubData(GL_UNIFORM_BUFFER, m_textureBlock.m_offsets[tuTexScale], m_textureBlockData.size(), pData);
}
void UniformBlock::updateLightParameters()
{
if (m_lightBlock.m_buffer == 0)
return;
GLbyte * pData = m_lightBlockData.data();
const u32 arraySize = m_lightBlock.m_offsets[luLightColor] / 8;
for (s32 i = 0; i <= gSP.numLights; ++i) {
memcpy(pData + m_lightBlock.m_offsets[luLightDirection] + arraySize*i, &gSP.lights[i].x, arraySize);
memcpy(pData + m_lightBlock.m_offsets[luLightColor] + arraySize*i, &gSP.lights[i].r, arraySize);
}
if (m_currentBuffer != m_lightBlock.m_buffer) {
m_currentBuffer = m_lightBlock.m_buffer;
glBindBuffer(GL_UNIFORM_BUFFER, m_lightBlock.m_buffer);
}
glBufferSubData(GL_UNIFORM_BUFFER, m_lightBlock.m_offsets[luLightDirection], m_lightBlockData.size(), pData);
}
#else
#define LocateUniform2(A) \
location.A.loc = glGetUniformLocation(program, #A);
void UniformBlock::bindWithShaderCombiner(ShaderCombiner * _pCombiner)
{
const u64 mux = _pCombiner->getMux();
const GLuint program = _pCombiner->m_program;
m_uniforms.emplace(mux, program);
UniformBlockLocation & location = m_uniforms.at(mux);
// Texture parameters
if (_pCombiner->usesTexture()) {
LocateUniform2(uTexScale);
LocateUniform2(uTexMask[0]);
LocateUniform2(uTexMask[1]);
LocateUniform2(uTexOffset[0]);
LocateUniform2(uTexOffset[1]);
LocateUniform2(uCacheScale[0]);
LocateUniform2(uCacheScale[1]);
LocateUniform2(uCacheOffset[0]);
LocateUniform2(uCacheOffset[1]);
LocateUniform2(uCacheShiftScale[0]);
LocateUniform2(uCacheShiftScale[1]);
LocateUniform2(uCacheFrameBuffer);
LocateUniform2(uTextureSize[0]);
LocateUniform2(uTextureSize[1]);
_updateTextureUniforms(location, _pCombiner->usesTile(0), _pCombiner->usesTile(1), true);
}
// Colors
LocateUniform2(uFogColor);
LocateUniform2(uCenterColor);
LocateUniform2(uScaleColor);
LocateUniform2(uBlendColor);
LocateUniform2(uEnvColor);
LocateUniform2(uPrimColor);
LocateUniform2(uPrimLod);
LocateUniform2(uK4);
LocateUniform2(uK5);
_updateColorUniforms(location, true);
// Lights
if (config.generalEmulation.enableHWLighting != 0 && GBI.isHWLSupported() && _pCombiner->usesShadeColor()) {
// locate lights uniforms
char buf[32];
for (s32 i = 0; i < 8; ++i) {
sprintf(buf, "uLightDirection[%d]", i);
location.uLightDirection[i].loc = glGetUniformLocation(program, buf);
sprintf(buf, "uLightColor[%d]", i);
location.uLightColor[i].loc = glGetUniformLocation(program, buf);
}
_updateLightUniforms(location, true);
}
}
void UniformBlock::_updateColorUniforms(UniformBlockLocation & _location, bool _bForce)
{
_location.uFogColor.set(&gDP.fogColor.r, _bForce);
_location.uCenterColor.set(&gDP.key.center.r, _bForce);
_location.uScaleColor.set(&gDP.key.scale.r, _bForce);
_location.uBlendColor.set(&gDP.blendColor.r, _bForce);
_location.uEnvColor.set(&gDP.envColor.r, _bForce);
_location.uPrimColor.set(&gDP.primColor.r, _bForce);
_location.uPrimLod.set(gDP.primColor.l, _bForce);
_location.uK4.set(gDP.convert.k4*0.0039215689f, _bForce);
_location.uK5.set(gDP.convert.k5*0.0039215689f, _bForce);
}
void UniformBlock::_updateTextureUniforms(UniformBlockLocation & _location, bool _bUsesT0, bool _bUsesT1, bool _bForce)
{
int nFB[2] = { 0, 0 };
const bool bUsesTile[2] = { _bUsesT0, _bUsesT1 };
TextureCache & cache = textureCache();
for (u32 t = 0; t < 2; ++t) {
if (!bUsesTile[t])
continue;
if (gSP.textureTile[t] != NULL) {
if (gSP.textureTile[t]->textureMode == TEXTUREMODE_BGIMAGE || gSP.textureTile[t]->textureMode == TEXTUREMODE_FRAMEBUFFER_BG) {
_location.uTexOffset[t].set(0.0f, 0.0f, _bForce);
_location.uTexMask[t].set(0.0f, 0.0f, _bForce);
}
else {
_location.uTexOffset[t].set(gSP.textureTile[t]->fuls, gSP.textureTile[t]->fult, _bForce);
_location.uTexMask[t].set(
gSP.textureTile[t]->masks > 0 ? (float)(1 << gSP.textureTile[t]->masks) : 0.0f,
gSP.textureTile[t]->maskt > 0 ? (float)(1 << gSP.textureTile[t]->maskt) : 0.0f,
_bForce);
}
}
if (cache.current[t] != NULL) {
f32 shiftScaleS = 1.0f;
f32 shiftScaleT = 1.0f;
getTextureShiftScale(t, cache, shiftScaleS, shiftScaleT);
_location.uCacheShiftScale[t].set(shiftScaleS, shiftScaleT, _bForce);
_location.uCacheScale[t].set(cache.current[t]->scaleS, cache.current[t]->scaleT, _bForce);
_location.uCacheOffset[t].set(cache.current[t]->offsetS, cache.current[t]->offsetT, _bForce);
_location.uTextureSize[t].set(cache.current[t]->realWidth, cache.current[t]->realHeight, _bForce);
nFB[t] = cache.current[t]->frameBufferTexture;
}
}
_location.uCacheFrameBuffer.set(nFB[0], nFB[1], _bForce);
_location.uTexScale.set(gSP.texture.scales, gSP.texture.scalet, _bForce);
}
void UniformBlock::_updateLightUniforms(UniformBlockLocation & _location, bool _bForce)
{
for (s32 i = 0; i <= gSP.numLights; ++i) {
_location.uLightDirection[i].set(&gSP.lights[i].x, _bForce);
_location.uLightColor[i].set(&gSP.lights[i].r, _bForce);
}
}
void UniformBlock::updateUniforms(ShaderCombiner * _pCombiner)
{
UniformBlockLocation & location = m_uniforms.at(_pCombiner->getMux());
_updateColorUniforms(location, false);
OGLRender::RENDER_STATE rs = video().getRender().getRenderState();
if ((rs == OGLRender::rsTriangle || rs == OGLRender::rsLine) && _pCombiner->usesTexture())
_updateTextureUniforms(location, _pCombiner->usesTile(0), _pCombiner->usesTile(1), false);
if (config.generalEmulation.enableHWLighting != 0 && GBI.isHWLSupported() && _pCombiner->usesShadeColor())
_updateLightUniforms(location, false);
}
#endif // GL_UNIFORMBLOCK_SUPPORT

View File

@ -35,6 +35,7 @@ public:
private:
friend class UniformBlock;
friend class UniformSet;
struct iUniform {
GLint loc;
@ -116,185 +117,6 @@ private:
int m_nInputs;
};
#ifdef GL_UNIFORMBLOCK_SUPPORT
class UniformBlock
{
public:
enum TextureUniforms {
tuTexScale,
tuTexMask,
tuTexOffset,
tuCacheScale,
tuCacheOffset,
tuCacheShiftScale,
tuCacheFrameBuffer,
tuTotal
};
enum ColorUniforms {
cuFogColor,
cuCenterColor,
cuScaleColor,
cuBlendColor,
cuEnvColor,
cuPrimColor,
cuPrimLod,
cuK4,
cuK5,
cuTotal
};
enum LightUniforms {
luLightDirection,
luLightColor,
luTotal
};
UniformBlock();
~UniformBlock();
void bindWithShaderCombiner(ShaderCombiner * _pCombiner);
void setColorData(ColorUniforms _index, u32 _dataSize, const void * _data);
void updateTextureParameters();
void updateLightParameters();
void updateUniforms(ShaderCombiner * _pCombiner) {}
private:
void _initTextureBuffer(GLuint _program);
void _initColorsBuffer(GLuint _program);
void _initLightBuffer(GLuint _program);
bool _isDataChanged(void * _pBuffer, const void * _pData, u32 _dataSize);
template <u32 _numUniforms, u32 _bindingPoint>
struct UniformBlockData
{
UniformBlockData() : m_buffer(0), m_blockBindingPoint(_bindingPoint)
{
memset(m_indices, 0, sizeof(m_indices));
memset(m_offsets, 0, sizeof(m_offsets));
}
~UniformBlockData()
{
if (m_buffer != 0) {
glDeleteBuffers(1, &m_buffer);
m_buffer = 0;
}
}
GLint initBuffer(GLuint _program, const char * _strBlockName, const char ** _strUniformNames)
{
GLuint blockIndex = glGetUniformBlockIndex(_program, _strBlockName);
if (blockIndex == GL_INVALID_INDEX)
return 0;
GLint blockSize, numUniforms;
glGetActiveUniformBlockiv(_program, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
glGetActiveUniformBlockiv(_program, blockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &numUniforms);
glGetUniformIndices(_program, numUniforms, _strUniformNames, m_indices);
glGetActiveUniformsiv(_program, numUniforms, m_indices, GL_UNIFORM_OFFSET, m_offsets);
glUniformBlockBinding(_program, blockIndex, m_blockBindingPoint);
glGenBuffers(1, &m_buffer);
return blockSize;
}
GLuint m_buffer;
GLuint m_blockBindingPoint;
GLuint m_indices[_numUniforms];
GLint m_offsets[_numUniforms];
};
GLuint m_currentBuffer;
UniformBlockData<tuTotal, 1> m_textureBlock;
UniformBlockData<cuTotal, 2> m_colorsBlock;
UniformBlockData<luTotal, 3> m_lightBlock;
std::vector<GLbyte> m_textureBlockData;
std::vector<GLbyte> m_colorsBlockData;
std::vector<GLbyte> m_lightBlockData;
};
#else
class UniformBlock
{
public:
UniformBlock() {}
~UniformBlock() {}
enum ColorUniforms {
cuFogColor,
cuCenterColor,
cuScaleColor,
cuBlendColor,
cuEnvColor,
cuPrimColor,
cuPrimLod,
cuK4,
cuK5,
cuTotal
};
void bindWithShaderCombiner(ShaderCombiner * _pCombiner);
void setColorData(ColorUniforms _index, u32 _dataSize, const void * _data) {}
void updateTextureParameters() {}
void updateLightParameters() {}
void updateUniforms(ShaderCombiner * _pCombiner);
private:
struct fv3Uniform {
GLint loc;
float val[3];
void set(float * _pVal, bool _force) {
const size_t szData = sizeof(float)* 3;
if (loc >= 0 && (_force || memcmp(val, _pVal, szData) != 0)) {
memcpy(val, _pVal, szData);
glUniform3fv(loc, 1, _pVal);
}
}
};
struct fv4Uniform {
GLint loc;
float val[4];
void set(float * _pVal, bool _force) {
const size_t szData = sizeof(float)* 4;
if (loc >= 0 && (_force || memcmp(val, _pVal, szData) != 0)) {
memcpy(val, _pVal, szData);
glUniform4fv(loc, 1, _pVal);
}
}
};
struct UniformBlockLocation
{
UniformBlockLocation(GLuint _program) : m_program(_program) {}
GLuint m_program;
// Texture parameters
ShaderCombiner::fv2Uniform uTexScale, uTexMask[2], uTexOffset[2], uCacheScale[2], uCacheOffset[2], uCacheShiftScale[2];
ShaderCombiner::iv2Uniform uCacheFrameBuffer, uTextureSize[2];
// Colors
fv4Uniform uFogColor, uCenterColor, uScaleColor, uBlendColor, uEnvColor, uPrimColor;
ShaderCombiner::fUniform uPrimLod, uK4, uK5;
// Lights
fv3Uniform uLightDirection[8], uLightColor[8];
};
void _updateColorUniforms(UniformBlockLocation & _location, bool _bForce);
void _updateTextureUniforms(UniformBlockLocation & _location, bool _bUsesT0, bool _bUsesT1, bool _bForce);
void _updateLightUniforms(UniformBlockLocation & _location, bool _bForce);
typedef std::map<u64, UniformBlockLocation> Uniforms;
Uniforms m_uniforms;
};
#endif // GL_UNIFORMBLOCK_SUPPORT
void InitShaderCombiner();
void DestroyShaderCombiner();

246
src/OGL3X/UniformBlock.cpp Normal file
View File

@ -0,0 +1,246 @@
#include "UniformBlock.h"
#include "../Config.h"
#include "../Textures.h"
static
const char * strTextureUniforms[UniformBlock::tuTotal] = {
"uTexScale",
"uTexMask",
"uTexOffset",
"uCacheScale",
"uCacheOffset",
"uCacheShiftScale",
"uCacheFrameBuffer"
};
static
const char * strColorUniforms[UniformBlock::cuTotal] = {
"uFogColor",
"uCenterColor",
"uScaleColor",
"uBlendColor",
"uEnvColor",
"uPrimColor",
"uPrimLod",
"uK4",
"uK5"
};
static
const char * strLightUniforms[UniformBlock::luTotal] = {
"uLightDirection",
"uLightColor"
};
UniformBlock::UniformBlock() : m_currentBuffer(0)
{
}
UniformBlock::~UniformBlock()
{
}
void UniformBlock::_initTextureBuffer(GLuint _program)
{
const GLint blockSize = m_textureBlock.initBuffer(_program, "TextureBlock", strTextureUniforms);
if (blockSize == 0)
return;
m_textureBlockData.resize(blockSize);
GLbyte * pData = m_textureBlockData.data();
memset(pData, 0, blockSize);
glBindBuffer(GL_UNIFORM_BUFFER, m_textureBlock.m_buffer);
glBufferData(GL_UNIFORM_BUFFER, blockSize, 0, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, m_textureBlock.m_blockBindingPoint, m_textureBlock.m_buffer);
updateTextureParameters();
}
void UniformBlock::_initColorsBuffer(GLuint _program)
{
const GLint blockSize = m_colorsBlock.initBuffer(_program, "ColorsBlock", strColorUniforms);
if (blockSize == 0)
return;
m_colorsBlockData.resize(blockSize);
GLbyte * pData = m_colorsBlockData.data();
memset(pData, 0, blockSize);
memcpy(pData + m_colorsBlock.m_offsets[cuFogColor], &gDP.fogColor.r, sizeof(f32)* 4);
memcpy(pData + m_colorsBlock.m_offsets[cuCenterColor], &gDP.key.center.r, sizeof(f32)* 4);
memcpy(pData + m_colorsBlock.m_offsets[cuScaleColor], &gDP.key.scale.r, sizeof(f32)* 4);
memcpy(pData + m_colorsBlock.m_offsets[cuEnvColor], &gDP.envColor.r, sizeof(f32)* 4);
memcpy(pData + m_colorsBlock.m_offsets[cuPrimColor], &gDP.primColor.r, sizeof(f32)* 4);
*(f32*)(pData + m_colorsBlock.m_offsets[cuPrimLod]) = gDP.primColor.l;
*(f32*)(pData + m_colorsBlock.m_offsets[cuK4]) = gDP.convert.k4*0.0039215689f;
*(f32*)(pData + m_colorsBlock.m_offsets[cuK5]) = gDP.convert.k5*0.0039215689f;
glBindBuffer(GL_UNIFORM_BUFFER, m_colorsBlock.m_buffer);
glBufferData(GL_UNIFORM_BUFFER, blockSize, pData, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, m_colorsBlock.m_blockBindingPoint, m_colorsBlock.m_buffer);
m_currentBuffer = m_colorsBlock.m_buffer;
}
void UniformBlock::_initLightBuffer(GLuint _program)
{
const GLint blockSize = m_lightBlock.initBuffer(_program, "LightBlock", strLightUniforms);
if (blockSize == 0)
return;
m_lightBlockData.resize(blockSize);
GLbyte * pData = m_lightBlockData.data();
memset(pData, 0, blockSize);
glBindBuffer(GL_UNIFORM_BUFFER, m_lightBlock.m_buffer);
glBufferData(GL_UNIFORM_BUFFER, blockSize, 0, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, m_lightBlock.m_blockBindingPoint, m_lightBlock.m_buffer);
updateLightParameters();
}
bool UniformBlock::_isDataChanged(void * _pBuffer, const void * _pData, u32 _dataSize)
{
u32 * pSrc = (u32*)_pData;
u32 * pDst = (u32*)_pBuffer;
u32 cnt = _dataSize / 4;
for (u32 i = 0; i < cnt; ++i) {
if (pSrc[i] != pDst[i]) {
memcpy(_pBuffer, _pData, _dataSize);
return true;
}
}
return false;
}
void UniformBlock::bindWithShaderCombiner(ShaderCombiner * _pCombiner)
{
const GLuint program = _pCombiner->m_program;
if (_pCombiner->usesTexture()) {
if (m_textureBlock.m_buffer == 0)
_initTextureBuffer(program);
else {
const GLint blockIndex = glGetUniformBlockIndex(program, "TextureBlock");
if (blockIndex != GL_INVALID_INDEX)
glUniformBlockBinding(program, blockIndex, m_textureBlock.m_blockBindingPoint);
}
}
if (m_colorsBlock.m_buffer == 0)
_initColorsBuffer(program);
else {
const GLint blockIndex = glGetUniformBlockIndex(program, "ColorsBlock");
if (blockIndex != GL_INVALID_INDEX)
glUniformBlockBinding(program, blockIndex, m_colorsBlock.m_blockBindingPoint);
}
if (_pCombiner->usesShadeColor() && config.generalEmulation.enableHWLighting != 0) {
if (m_lightBlock.m_buffer == 0)
_initLightBuffer(program);
else {
const GLint blockIndex = glGetUniformBlockIndex(program, "LightBlock");
if (blockIndex != GL_INVALID_INDEX)
glUniformBlockBinding(program, blockIndex, m_lightBlock.m_blockBindingPoint);
}
}
}
void UniformBlock::setColorData(ColorUniforms _index, u32 _dataSize, const void * _data)
{
if (m_colorsBlock.m_buffer == 0)
return;
if (!_isDataChanged(m_colorsBlockData.data() + m_colorsBlock.m_offsets[_index], _data, _dataSize))
return;
if (m_currentBuffer != m_colorsBlock.m_buffer) {
m_currentBuffer = m_colorsBlock.m_buffer;
glBindBuffer(GL_UNIFORM_BUFFER, m_colorsBlock.m_buffer);
}
glBufferSubData(GL_UNIFORM_BUFFER, m_colorsBlock.m_offsets[_index], _dataSize, _data);
}
void UniformBlock::updateTextureParameters()
{
if (m_textureBlock.m_buffer == 0)
return;
GLbyte * pData = m_textureBlockData.data();
f32 texScale[4] = { gSP.texture.scales, gSP.texture.scalet, 0, 0 };
memcpy(pData + m_textureBlock.m_offsets[tuTexScale], texScale, m_textureBlock.m_offsets[tuTexMask] - m_textureBlock.m_offsets[tuTexScale]);
f32 texOffset[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
f32 texMask[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
if (gSP.textureTile[0] != NULL) {
if (gSP.textureTile[0]->textureMode != TEXTUREMODE_BGIMAGE && gSP.textureTile[0]->textureMode != TEXTUREMODE_FRAMEBUFFER_BG) {
texOffset[0] = gSP.textureTile[0]->fuls;
texOffset[1] = gSP.textureTile[0]->fult;
texMask[0] = gSP.textureTile[0]->masks > 0 ? (float)(1 << gSP.textureTile[0]->masks) : 0.0f;
texMask[1] = gSP.textureTile[0]->maskt > 0 ? (float)(1 << gSP.textureTile[0]->maskt) : 0.0f;
}
}
if (gSP.textureTile[1] != 0) {
texOffset[4] = gSP.textureTile[1]->fuls;
texOffset[5] = gSP.textureTile[1]->fult;
texMask[4] = gSP.textureTile[1]->masks > 0 ? (float)(1 << gSP.textureTile[1]->masks) : 0.0f;
texMask[5] = gSP.textureTile[1]->maskt > 0 ? (float)(1 << gSP.textureTile[1]->maskt) : 0.0f;
}
memcpy(pData + m_textureBlock.m_offsets[tuTexMask], texMask, m_textureBlock.m_offsets[tuTexOffset] - m_textureBlock.m_offsets[tuTexMask]);
memcpy(pData + m_textureBlock.m_offsets[tuTexOffset], texOffset, m_textureBlock.m_offsets[tuCacheScale] - m_textureBlock.m_offsets[tuTexOffset]);
f32 texCacheScale[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
f32 texCacheOffset[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
f32 texCacheShiftScale[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
GLint texCacheFrameBuffer[4] = { 0, 0, 0, 0 };
TextureCache & cache = textureCache();
if (cache.current[0]) {
texCacheScale[0] = cache.current[0]->scaleS;
texCacheScale[1] = cache.current[0]->scaleT;
texCacheOffset[0] = cache.current[0]->offsetS;
texCacheOffset[1] = cache.current[0]->offsetT;
f32 shiftScaleS = 1.0f;
f32 shiftScaleT = 1.0f;
getTextureShiftScale(0, cache, shiftScaleS, shiftScaleT);
texCacheShiftScale[0] = shiftScaleS;
texCacheShiftScale[1] = shiftScaleT;
texCacheFrameBuffer[0] = cache.current[0]->frameBufferTexture;
}
if (cache.current[1]) {
texCacheScale[4] = cache.current[1]->scaleS;
texCacheScale[5] = cache.current[1]->scaleT;
texCacheOffset[4] = cache.current[1]->offsetS;
texCacheOffset[5] = cache.current[1]->offsetT;
f32 shiftScaleS = 1.0f;
f32 shiftScaleT = 1.0f;
getTextureShiftScale(1, cache, shiftScaleS, shiftScaleT);
texCacheShiftScale[4] = shiftScaleS;
texCacheShiftScale[5] = shiftScaleT;
texCacheFrameBuffer[1] = cache.current[1]->frameBufferTexture;
}
memcpy(pData + m_textureBlock.m_offsets[tuCacheScale], texCacheScale, m_textureBlock.m_offsets[tuCacheOffset] - m_textureBlock.m_offsets[tuCacheScale]);
memcpy(pData + m_textureBlock.m_offsets[tuCacheOffset], texCacheOffset, m_textureBlock.m_offsets[tuCacheShiftScale] - m_textureBlock.m_offsets[tuCacheOffset]);
memcpy(pData + m_textureBlock.m_offsets[tuCacheShiftScale], texCacheShiftScale, m_textureBlock.m_offsets[tuCacheFrameBuffer] - m_textureBlock.m_offsets[tuCacheShiftScale]);
memcpy(pData + m_textureBlock.m_offsets[tuCacheFrameBuffer], texCacheFrameBuffer, m_textureBlockData.size() - m_textureBlock.m_offsets[tuCacheFrameBuffer]);
if (m_currentBuffer != m_textureBlock.m_buffer) {
m_currentBuffer = m_textureBlock.m_buffer;
glBindBuffer(GL_UNIFORM_BUFFER, m_textureBlock.m_buffer);
}
glBufferSubData(GL_UNIFORM_BUFFER, m_textureBlock.m_offsets[tuTexScale], m_textureBlockData.size(), pData);
}
void UniformBlock::updateLightParameters()
{
if (m_lightBlock.m_buffer == 0)
return;
GLbyte * pData = m_lightBlockData.data();
const u32 arraySize = m_lightBlock.m_offsets[luLightColor] / 8;
for (s32 i = 0; i <= gSP.numLights; ++i) {
memcpy(pData + m_lightBlock.m_offsets[luLightDirection] + arraySize*i, &gSP.lights[i].x, arraySize);
memcpy(pData + m_lightBlock.m_offsets[luLightColor] + arraySize*i, &gSP.lights[i].r, arraySize);
}
if (m_currentBuffer != m_lightBlock.m_buffer) {
m_currentBuffer = m_lightBlock.m_buffer;
glBindBuffer(GL_UNIFORM_BUFFER, m_lightBlock.m_buffer);
}
glBufferSubData(GL_UNIFORM_BUFFER, m_lightBlock.m_offsets[luLightDirection], m_lightBlockData.size(), pData);
}
UniformCollection * createUniformCollection()
{
return new UniformBlock();
}

76
src/OGL3X/UniformBlock.h Normal file
View File

@ -0,0 +1,76 @@
#ifndef UNIFORM_BLOCK_H
#define UNIFORM_BLOCK_H
#include "../UniformCollection.h"
class UniformBlock : public UniformCollection
{
public:
UniformBlock();
~UniformBlock();
virtual void bindWithShaderCombiner(ShaderCombiner * _pCombiner);
virtual void setColorData(ColorUniforms _index, u32 _dataSize, const void * _data);
virtual void updateTextureParameters();
virtual void updateLightParameters();
virtual void updateUniforms(ShaderCombiner * _pCombiner) {}
private:
void _initTextureBuffer(GLuint _program);
void _initColorsBuffer(GLuint _program);
void _initLightBuffer(GLuint _program);
bool _isDataChanged(void * _pBuffer, const void * _pData, u32 _dataSize);
template <u32 _numUniforms, u32 _bindingPoint>
struct UniformBlockData
{
UniformBlockData() : m_buffer(0), m_blockBindingPoint(_bindingPoint)
{
memset(m_indices, 0, sizeof(m_indices));
memset(m_offsets, 0, sizeof(m_offsets));
}
~UniformBlockData()
{
if (m_buffer != 0) {
glDeleteBuffers(1, &m_buffer);
m_buffer = 0;
}
}
GLint initBuffer(GLuint _program, const char * _strBlockName, const char ** _strUniformNames)
{
GLuint blockIndex = glGetUniformBlockIndex(_program, _strBlockName);
if (blockIndex == GL_INVALID_INDEX)
return 0;
GLint blockSize, numUniforms;
glGetActiveUniformBlockiv(_program, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
glGetActiveUniformBlockiv(_program, blockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &numUniforms);
glGetUniformIndices(_program, numUniforms, _strUniformNames, m_indices);
glGetActiveUniformsiv(_program, numUniforms, m_indices, GL_UNIFORM_OFFSET, m_offsets);
glUniformBlockBinding(_program, blockIndex, m_blockBindingPoint);
glGenBuffers(1, &m_buffer);
return blockSize;
}
GLuint m_buffer;
GLuint m_blockBindingPoint;
GLuint m_indices[_numUniforms];
GLint m_offsets[_numUniforms];
};
GLuint m_currentBuffer;
UniformBlockData<tuTotal, 1> m_textureBlock;
UniformBlockData<cuTotal, 2> m_colorsBlock;
UniformBlockData<luTotal, 3> m_lightBlock;
std::vector<GLbyte> m_textureBlockData;
std::vector<GLbyte> m_colorsBlockData;
std::vector<GLbyte> m_lightBlockData;
};
#endif // UNIFORM_BLOCK_H

47
src/UniformCollection.h Normal file
View File

@ -0,0 +1,47 @@
#ifndef UNIFORM_COLLECTION_H
#define UNIFORM_COLLECTION_H
#include "GLSLCombiner.h"
class UniformCollection {
public:
enum TextureUniforms {
tuTexScale,
tuTexMask,
tuTexOffset,
tuCacheScale,
tuCacheOffset,
tuCacheShiftScale,
tuCacheFrameBuffer,
tuTotal
};
enum ColorUniforms {
cuFogColor,
cuCenterColor,
cuScaleColor,
cuBlendColor,
cuEnvColor,
cuPrimColor,
cuPrimLod,
cuK4,
cuK5,
cuTotal
};
enum LightUniforms {
luLightDirection,
luLightColor,
luTotal
};
virtual void bindWithShaderCombiner(ShaderCombiner * _pCombiner) = 0;
virtual void setColorData(ColorUniforms _index, u32 _dataSize, const void * _data) = 0;
virtual void updateTextureParameters() = 0;
virtual void updateLightParameters() = 0;
virtual void updateUniforms(ShaderCombiner * _pCombiner) = 0;
};
UniformCollection * createUniformCollection();
#endif // UNIFORM_COLLECTION_H