diff --git a/Core/MemMap.h b/Core/MemMap.h index 7cd098555b..e82ed7b272 100644 --- a/Core/MemMap.h +++ b/Core/MemMap.h @@ -241,7 +241,6 @@ inline void Write_Float(float f, u32 address) // Reads a zero-terminated string from memory at the address. void GetString(std::string& _string, const u32 _Address); u8* GetPointer(const u32 address); -bool IsValidAddress(const u32 address); bool IsRAMAddress(const u32 address); bool IsVRAMAddress(const u32 address); diff --git a/GPU/GLES/ShaderManager.cpp b/GPU/GLES/ShaderManager.cpp index 6a900a25a2..e31a39d12c 100644 --- a/GPU/GLES/ShaderManager.cpp +++ b/GPU/GLES/ShaderManager.cpp @@ -198,6 +198,36 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs, u32 vertType, bool useHWTrans if (-1 != glGetAttribLocation(program, "color0")) attrMask |= 1 << ATTR_COLOR0; if (-1 != glGetAttribLocation(program, "color1")) attrMask |= 1 << ATTR_COLOR1; + availableUniforms = 0; + if (u_proj != -1) availableUniforms |= DIRTY_PROJMATRIX; + if (u_proj_through != -1) availableUniforms |= DIRTY_PROJTHROUGHMATRIX; + if (u_texenv != -1) availableUniforms |= DIRTY_TEXENV; + if (u_alphacolorref != -1) availableUniforms |= DIRTY_ALPHACOLORREF; + if (u_colormask != -1) availableUniforms |= DIRTY_COLORMASK; + if (u_fogcolor != -1) availableUniforms |= DIRTY_FOGCOLOR; + if (u_fogcoef != -1) availableUniforms |= DIRTY_FOGCOEF; + if (u_texenv != -1) availableUniforms |= DIRTY_TEXENV; + if (u_uvscaleoffset != -1) availableUniforms |= DIRTY_UVSCALEOFFSET; + if (u_world != -1) availableUniforms |= DIRTY_WORLDMATRIX; + if (u_view != -1) availableUniforms |= DIRTY_VIEWMATRIX; + if (u_texmtx != -1) availableUniforms |= DIRTY_TEXMATRIX; + // Looping up to numBones lets us avoid checking u_bone[i] + for (int i = 0; i < numBones; i++) { + if (u_bone[i] != -1) + availableUniforms |= DIRTY_BONEMATRIX0 << i; + } + if (u_ambient != -1) availableUniforms |= DIRTY_AMBIENT; + if (u_matambientalpha != -1) availableUniforms |= DIRTY_MATAMBIENTALPHA; + if (u_matdiffuse != -1) availableUniforms |= DIRTY_MATDIFFUSE; + if (u_matemissive != -1) availableUniforms |= DIRTY_MATEMISSIVE; + if (u_matspecular != -1) availableUniforms |= DIRTY_MATSPECULAR; + for (int i = 0; i < 4; i++) { + if (u_lightdir[i] != -1 || + u_lightspecular[i] != -1 || + u_lightpos[i] != -1) + availableUniforms |= DIRTY_LIGHT0 << i; + } + glUseProgram(program); // Default uniform values @@ -290,7 +320,7 @@ static void SetMatrix4x3(int uniform, const float *m4x3) { void LinkedShader::use(u32 vertType, LinkedShader *previous) { glUseProgram(program); - updateUniforms(vertType); + UpdateUniforms(vertType); int enable, disable; if (previous) { enable = attrMask & ~previous->attrMask; @@ -314,12 +344,13 @@ void LinkedShader::stop() { } } -void LinkedShader::updateUniforms(u32 vertType) { - if (!dirtyUniforms) +void LinkedShader::UpdateUniforms(u32 vertType) { + u32 dirty = dirtyUniforms & availableUniforms; + if (!dirty) return; // Update any dirty uniforms before we draw - if (u_proj != -1 && (dirtyUniforms & DIRTY_PROJMATRIX)) { + if (dirty & DIRTY_PROJMATRIX) { float flippedMatrix[16]; memcpy(flippedMatrix, gstate.projMatrix, 16 * sizeof(float)); if (gstate_c.vpHeight < 0) { @@ -332,25 +363,25 @@ void LinkedShader::updateUniforms(u32 vertType) { } glUniformMatrix4fv(u_proj, 1, GL_FALSE, flippedMatrix); } - if (u_proj_through != -1 && (dirtyUniforms & DIRTY_PROJTHROUGHMATRIX)) + if (dirty & DIRTY_PROJTHROUGHMATRIX) { Matrix4x4 proj_through; proj_through.setOrtho(0.0f, gstate_c.curRTWidth, gstate_c.curRTHeight, 0, 0, 1); glUniformMatrix4fv(u_proj_through, 1, GL_FALSE, proj_through.getReadPtr()); } - if (u_texenv != -1 && (dirtyUniforms & DIRTY_TEXENV)) { + if (dirty & DIRTY_TEXENV) { SetColorUniform3(u_texenv, gstate.texenvcolor); } - if (u_alphacolorref != -1 && (dirtyUniforms & DIRTY_ALPHACOLORREF)) { + if (dirty & DIRTY_ALPHACOLORREF) { SetColorUniform3Alpha255(u_alphacolorref, gstate.getColorTestRef(), gstate.getAlphaTestRef()); } - if (u_colormask != -1 && (dirtyUniforms & DIRTY_COLORMASK)) { + if (dirty & DIRTY_COLORMASK) { SetColorUniform3(u_colormask, gstate.colormask); } - if (u_fogcolor != -1 && (dirtyUniforms & DIRTY_FOGCOLOR)) { + if (dirty & DIRTY_FOGCOLOR) { SetColorUniform3(u_fogcolor, gstate.fogcolor); } - if (u_fogcoef != -1 && (dirtyUniforms & DIRTY_FOGCOEF)) { + if (dirty & DIRTY_FOGCOEF) { const float fogcoef[2] = { getFloat24(gstate.fog1), getFloat24(gstate.fog2), @@ -359,7 +390,7 @@ void LinkedShader::updateUniforms(u32 vertType) { } // Texturing - if (u_uvscaleoffset != -1 && (dirtyUniforms & DIRTY_UVSCALEOFFSET)) { + if (dirty & DIRTY_UVSCALEOFFSET) { float uvscaleoff[4]; if (gstate.isModeThrough()) { // We never get here because we don't use HW transform with through mode. @@ -393,13 +424,13 @@ void LinkedShader::updateUniforms(u32 vertType) { } // Transform - if (u_world != -1 && (dirtyUniforms & DIRTY_WORLDMATRIX)) { + if (dirty & DIRTY_WORLDMATRIX) { SetMatrix4x3(u_world, gstate.worldMatrix); } - if (u_view != -1 && (dirtyUniforms & DIRTY_VIEWMATRIX)) { + if (dirty & DIRTY_VIEWMATRIX) { SetMatrix4x3(u_view, gstate.viewMatrix); } - if (u_texmtx != -1 && (dirtyUniforms & DIRTY_TEXMATRIX)) { + if (dirty & DIRTY_TEXMATRIX) { SetMatrix4x3(u_texmtx, gstate.tgenMatrix); } @@ -431,7 +462,7 @@ void LinkedShader::updateUniforms(u32 vertType) { #else float bonetemp[16]; for (int i = 0; i < numBones; i++) { - if (dirtyUniforms & (DIRTY_BONEMATRIX0 << i)) { + if (dirty & (DIRTY_BONEMATRIX0 << i)) { ConvertMatrix4x3To4x4(gstate.boneMatrix + 12 * i, bonetemp); glUniformMatrix4fv(u_bone[i], 1, GL_FALSE, bonetemp); } @@ -439,24 +470,24 @@ void LinkedShader::updateUniforms(u32 vertType) { #endif // Lighting - if (u_ambient != -1 && (dirtyUniforms & DIRTY_AMBIENT)) { + if (dirtyUniforms & DIRTY_AMBIENT) { SetColorUniform3Alpha(u_ambient, gstate.ambientcolor, gstate.getAmbientA()); } - if (u_matambientalpha != -1 && (dirtyUniforms & DIRTY_MATAMBIENTALPHA)) { + if (dirtyUniforms & DIRTY_MATAMBIENTALPHA) { SetColorUniform3Alpha(u_matambientalpha, gstate.materialambient, gstate.getMaterialAmbientA()); } - if (u_matdiffuse != -1 && (dirtyUniforms & DIRTY_MATDIFFUSE)) { + if (dirtyUniforms & DIRTY_MATDIFFUSE) { SetColorUniform3(u_matdiffuse, gstate.materialdiffuse); } - if (u_matemissive != -1 && (dirtyUniforms & DIRTY_MATEMISSIVE)) { + if (dirtyUniforms & DIRTY_MATEMISSIVE) { SetColorUniform3(u_matemissive, gstate.materialemissive); } - if (u_matspecular != -1 && (dirtyUniforms & DIRTY_MATSPECULAR)) { + if (dirtyUniforms & DIRTY_MATSPECULAR) { SetColorUniform3ExtraFloat(u_matspecular, gstate.materialspecular, getFloat24(gstate.materialspecularcoef)); } for (int i = 0; i < 4; i++) { - if (dirtyUniforms & (DIRTY_LIGHT0 << i)) { + if (dirty & (DIRTY_LIGHT0 << i)) { if (gstate.isDirectionalLight(i)) { // Prenormalize float x = gstate_c.lightpos[i][0]; @@ -553,7 +584,7 @@ LinkedShader *ShaderManager::ApplyShader(int prim, u32 vertType) { // Just update uniforms if this is the same shader as last time. if (lastShader_ != 0 && VSID == lastVSID_ && FSID == lastFSID_) { - lastShader_->updateUniforms(vertType); + lastShader_->UpdateUniforms(vertType); return lastShader_; // Already all set. } diff --git a/GPU/GLES/ShaderManager.h b/GPU/GLES/ShaderManager.h index f5f1450579..5dd831c4e9 100644 --- a/GPU/GLES/ShaderManager.h +++ b/GPU/GLES/ShaderManager.h @@ -45,12 +45,13 @@ public: void use(u32 vertType, LinkedShader *previous); void stop(); - void updateUniforms(u32 vertType); + void UpdateUniforms(u32 vertType); // Set to false if the VS failed, happens on Mali-400 a lot for complex shaders. bool useHWTransform_; uint32_t program; + u32 availableUniforms; u32 dirtyUniforms; // Present attributes in the shader. @@ -104,7 +105,7 @@ enum DIRTY_FOGCOEF = (1 << 3), DIRTY_TEXENV = (1 << 4), DIRTY_ALPHACOLORREF = (1 << 5), - DIRTY_COLORREF = (1 << 6), + // 1 << 6 is free! DIRTY_COLORMASK = (1 << 7), DIRTY_LIGHT0 = (1 << 8), DIRTY_LIGHT1 = (1 << 9), @@ -116,7 +117,7 @@ enum DIRTY_MATEMISSIVE = (1 << 14), DIRTY_AMBIENT = (1 << 15), DIRTY_MATAMBIENTALPHA = (1 << 16), - DIRTY_MATERIAL = (1 << 17), // let's set all 4 together (emissive ambient diffuse specular). We hide specular coef in specular.a + // 1 << 17 is free! DIRTY_UVSCALEOFFSET = (1 << 18), // this will be dirtied ALL THE TIME... maybe we'll need to do "last value with this shader compares" DIRTY_WORLDMATRIX = (1 << 21),