From bbc292c21000ee3532c1fb4e955dc03951a6e2f6 Mon Sep 17 00:00:00 2001 From: degasus Date: Wed, 13 Feb 2013 13:12:19 +0100 Subject: [PATCH] merge Vertex and PixelShaderCache into ProgramShaderCache this is the first step, uniform handling is still missing --- .../Plugin_VideoOGL/Plugin_VideoOGL.vcxproj | 2 - .../Plugin_VideoOGL.vcxproj.filters | 6 - .../Plugin_VideoOGL/Src/PixelShaderCache.cpp | 135 +------ .../Plugin_VideoOGL/Src/PixelShaderCache.h | 83 ---- .../Plugin_VideoOGL/Src/PostProcessing.cpp | 14 +- .../Src/ProgramShaderCache.cpp | 376 ++++++++++++------ .../Plugin_VideoOGL/Src/ProgramShaderCache.h | 129 +++--- .../Plugin_VideoOGL/Src/RasterFont.cpp | 20 +- Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 29 +- .../Plugin_VideoOGL/Src/TextureCache.cpp | 32 +- .../Plugin_VideoOGL/Src/TextureConverter.cpp | 60 ++- .../Plugin_VideoOGL/Src/VertexManager.cpp | 17 +- .../Plugin_VideoOGL/Src/VertexShaderCache.cpp | 121 +----- .../Plugin_VideoOGL/Src/VertexShaderCache.h | 75 ---- Source/Plugins/Plugin_VideoOGL/Src/main.cpp | 6 - 15 files changed, 389 insertions(+), 716 deletions(-) delete mode 100644 Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.h delete mode 100644 Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.h diff --git a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj index c5e741a66b..e0458d9a01 100644 --- a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj +++ b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj @@ -224,7 +224,6 @@ - @@ -234,7 +233,6 @@ - diff --git a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters index 3437f0a8ae..27bb563c52 100644 --- a/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters +++ b/Source/Plugins/Plugin_VideoOGL/Plugin_VideoOGL.vcxproj.filters @@ -63,9 +63,6 @@ Render - - Render - Render @@ -78,9 +75,6 @@ Render - - Render - diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp index eaf3562986..1d3865851a 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp @@ -28,7 +28,6 @@ #include "Render.h" #include "VertexShaderGen.h" #include "ProgramShaderCache.h" -#include "PixelShaderCache.h" #include "PixelShaderManager.h" #include "OnScreenDisplay.h" #include "StringUtil.h" @@ -38,136 +37,6 @@ namespace OGL { -static int s_nMaxPixelInstructions; -PixelShaderCache::PSCache PixelShaderCache::PixelShaders; -PIXELSHADERUID PixelShaderCache::s_curuid; -bool PixelShaderCache::s_displayCompileAlert; -GLuint PixelShaderCache::CurrentShader; -bool PixelShaderCache::ShaderEnabled; - -PixelShaderCache::PSCacheEntry* PixelShaderCache::last_entry = NULL; -PIXELSHADERUID PixelShaderCache::last_uid; - -void PixelShaderCache::Init() -{ - ShaderEnabled = true; - CurrentShader = 0; - last_entry = NULL; - GL_REPORT_ERRORD(); - - s_displayCompileAlert = true; -} - -void PixelShaderCache::Shutdown() -{ - PSCache::iterator iter = PixelShaders.begin(); - for (; iter != PixelShaders.end(); iter++) - iter->second.Destroy(); - PixelShaders.clear(); -} - -FRAGMENTSHADER* PixelShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 components) -{ - PIXELSHADERUID uid; - GetPixelShaderId(&uid, dstAlphaMode, components); - - // Check if the shader is already set - if (last_entry) - { - if (uid == last_uid) - { - GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); - ValidatePixelShaderIDs(API_OPENGL, last_entry->safe_uid, last_entry->shader.strprog, dstAlphaMode, components); - return &last_entry->shader; - } - } - - last_uid = uid; - - PSCache::iterator iter = PixelShaders.find(uid); - if (iter != PixelShaders.end()) - { - PSCacheEntry &entry = iter->second; - last_entry = &entry; - - GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); - ValidatePixelShaderIDs(API_OPENGL, entry.safe_uid, entry.shader.strprog, dstAlphaMode, components); - return &last_entry->shader; - } - - // Make an entry in the table - PSCacheEntry& newentry = PixelShaders[uid]; - last_entry = &newentry; - const char *code = GeneratePixelShaderCode(dstAlphaMode, API_OPENGL, components); - - if (g_ActiveConfig.bEnableShaderDebugging && code) - { - GetSafePixelShaderId(&newentry.safe_uid, dstAlphaMode, components); - newentry.shader.strprog = code; - } - -#if defined(_DEBUG) || defined(DEBUGFAST) - if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) { - static int counter = 0; - char szTemp[MAX_PATH]; - sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++); - - SaveData(szTemp, code); - } -#endif - - if (!code || !CompilePixelShader(newentry.shader, code)) { - GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true); - return NULL; - } - - INCSTAT(stats.numPixelShadersCreated); - SETSTAT(stats.numPixelShadersAlive, PixelShaders.size()); - GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); - return &last_entry->shader; -} - -bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram) -{ - GLuint result = glCreateShader(GL_FRAGMENT_SHADER); - - glShaderSource(result, 1, &pstrprogram, NULL); - glCompileShader(result); -#if defined(_DEBUG) || defined(DEBUGFAST) || defined(DEBUG_GLSL) - GLsizei length = 0; - glGetShaderiv(result, GL_INFO_LOG_LENGTH, &length); - if (length > 1) - { - GLsizei charsWritten; - GLchar* infoLog = new GLchar[length]; - glGetShaderInfoLog(result, length, &charsWritten, infoLog); - ERROR_LOG(VIDEO, "PS Shader info log:\n%s", infoLog); - char szTemp[MAX_PATH]; - sprintf(szTemp, "ps_%d.txt", result); - FILE *fp = fopen(szTemp, "wb"); - fwrite(infoLog, strlen(infoLog), 1, fp); - fwrite(pstrprogram, strlen(pstrprogram), 1, fp); - fclose(fp); - delete[] infoLog; - } - - GLint compileStatus; - glGetShaderiv(result, GL_COMPILE_STATUS, &compileStatus); - if (compileStatus != GL_TRUE) - { - // Compile failed - ERROR_LOG(VIDEO, "Shader compilation failed; see info log"); - - // Don't try to use this shader - glDeleteShader(result); - return false; - } -#endif - (void)GL_REPORT_ERROR(); - ps.glprogid = result; - return true; -} - void SetPSConstant4fvByName(const char * name, unsigned int offset, const float *f, const unsigned int count = 1) { ProgramShaderCache::PCacheEntry tmp = ProgramShaderCache::GetShaderProgram(); @@ -175,11 +44,11 @@ void SetPSConstant4fvByName(const char * name, unsigned int offset, const float { if (!strcmp(name, UniformNames[a])) { - if (tmp.UniformLocations[a] == -1) + if (tmp.shader.UniformLocations[a] == -1) return; else { - glUniform4fv(tmp.UniformLocations[a] + offset, count, f); + glUniform4fv(tmp.shader.UniformLocations[a] + offset, count, f); return; } } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.h b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.h deleted file mode 100644 index a3b85c3fcc..0000000000 --- a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.h +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (C) 2003 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#ifndef _PIXELSHADERCACHE_H_ -#define _PIXELSHADERCACHE_H_ - -#include -#include - -#include "BPMemory.h" -#include "PixelShaderGen.h" - -namespace OGL -{ - -struct FRAGMENTSHADER -{ - FRAGMENTSHADER() : glprogid(0) { } - void Destroy() - { - if (glprogid) - { - glDeleteShader(glprogid); - glprogid = 0; - } - } - GLuint glprogid; // opengl program id - - std::string strprog; -}; - -class PixelShaderCache -{ - struct PSCacheEntry - { - FRAGMENTSHADER shader; - PSCacheEntry() {} - ~PSCacheEntry() {} - void Destroy() - { - shader.Destroy(); - } - PIXELSHADERUIDSAFE safe_uid; - }; - - typedef std::map PSCache; - - static PSCache PixelShaders; - - static PIXELSHADERUID s_curuid; // the current pixel shader uid (progressively changed as memory is written) - - static bool s_displayCompileAlert; - - static GLuint CurrentShader; - static PSCacheEntry* last_entry; - static PIXELSHADERUID last_uid; - - static bool ShaderEnabled; - -public: - static void Init(); - static void Shutdown(); - - static FRAGMENTSHADER* SetShader(DSTALPHA_MODE dstAlphaMode, u32 components); - static bool CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram); -}; -} // namespace OGL - -#endif // _PIXELSHADERCACHE_H_ diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.cpp index 531af03aa2..c69932a355 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/PostProcessing.cpp @@ -20,7 +20,7 @@ #include "VideoConfig.h" #include "GLUtil.h" #include "PostProcessing.h" -#include "PixelShaderCache.h" +#include "ProgramShaderCache.h" namespace OGL { @@ -29,7 +29,7 @@ namespace PostProcessing { static std::string s_currentShader; -static FRAGMENTSHADER s_shader; +static SHADER s_shader; void Init() { @@ -63,10 +63,10 @@ bool ApplyShader() std::string code; if (File::ReadFileToString(true, s_currentShader.c_str(), code)) { - if (!PixelShaderCache::CompilePixelShader(s_shader, code.c_str())) - { - ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", s_currentShader.c_str()); - } + //if (!ProgramShaderCache::CompileShader(s_shader, "#version130\n...", code.c_str())) + //{ + // ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", s_currentShader.c_str()); + //} } else { @@ -78,7 +78,7 @@ bool ApplyShader() // TODO: Convert PP shaders to GLSL if (s_shader.glprogid != 0) { - // SetBothShaders(s_shader, 0); + s_shader.Bind(); return true; } else diff --git a/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp index 5481f26541..fcffa175c6 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.cpp @@ -18,37 +18,30 @@ #include "ProgramShaderCache.h" #include "MathUtil.h" #include "StreamBuffer.h" +#include "Debugger.h" +#include "Statistics.h" namespace OGL { static const u32 UBO_LENGTH = 4*1024*1024; -GLuint ProgramShaderCache::CurrentProgram = 0; +static GLuint CurrentProgram = 0; ProgramShaderCache::PCache ProgramShaderCache::pshaders; GLintptr ProgramShaderCache::s_vs_data_offset; u8 *ProgramShaderCache::s_ubo_buffer; u32 ProgramShaderCache::s_ubo_buffer_size; bool ProgramShaderCache::s_ubo_dirty; -LinearDiskCache g_program_disk_cache; +LinearDiskCache g_program_disk_cache; GLenum ProgramFormat; GLuint ProgramShaderCache::PCacheEntry::prog_format = 0; -u64 ProgramShaderCache::CurrentShaderProgram; - static StreamBuffer *s_buffer; -u64 Create_Pair(u32 key1, u32 key2) -{ - return (((u64)key1) << 32) | key2; -} -void Get_Pair(u64 key, u32 *key1, u32 *key2) -{ - *key1 = (key & 0xFFFFFFFF00000000) >> 32; - *key2 = key & 0xFFFFFFFF; -} +ProgramShaderCache::PCacheEntry* ProgramShaderCache::last_entry; +SHADERUID ProgramShaderCache::last_uid; const char *UniformNames[NUM_UNIFORMS] = { @@ -75,18 +68,21 @@ const char *UniformNames[NUM_UNIFORMS] = I_DEPTHPARAMS, }; -void ProgramShaderCache::SetProgramVariables(PCacheEntry &entry) +void SHADER::SetProgramVariables() { + // glsl shader must be bind to set samplers + Bind(); + // Bind UBO if (g_ActiveConfig.backend_info.bSupportsGLSLUBO) { - GLint PSBlock_id = glGetUniformBlockIndex(entry.prog_id, "PSBlock"); - GLint VSBlock_id = glGetUniformBlockIndex(entry.prog_id, "VSBlock"); + GLint PSBlock_id = glGetUniformBlockIndex(glprogid, "PSBlock"); + GLint VSBlock_id = glGetUniformBlockIndex(glprogid, "VSBlock"); if(PSBlock_id != -1) - glUniformBlockBinding(entry.prog_id, PSBlock_id, 1); + glUniformBlockBinding(glprogid, PSBlock_id, 1); if(VSBlock_id != -1) - glUniformBlockBinding(entry.prog_id, VSBlock_id, 2); + glUniformBlockBinding(glprogid, VSBlock_id, 2); } // We cache our uniform locations for now @@ -94,12 +90,12 @@ void ProgramShaderCache::SetProgramVariables(PCacheEntry &entry) // We can remove this // (Sonicadvance): For some reason this fails on my hardware - //glGetUniformIndices(entry.prog_id, NUM_UNIFORMS, UniformNames, entry.UniformLocations); + //glGetUniformIndices(glprogid, NUM_UNIFORMS, UniformNames, UniformLocations); // Got to do it this crappy way. - entry.UniformLocations[0] = glGetUniformLocation(entry.prog_id, UniformNames[0]); + UniformLocations[0] = glGetUniformLocation(glprogid, UniformNames[0]); if (!g_ActiveConfig.backend_info.bSupportsGLSLUBO) for (int a = 1; a < NUM_UNIFORMS; ++a) - entry.UniformLocations[a] = glGetUniformLocation(entry.prog_id, UniformNames[a]); + UniformLocations[a] = glGetUniformLocation(glprogid, UniformNames[a]); // Bind Texture Sampler for (int a = 0; a <= 9; ++a) @@ -108,134 +104,55 @@ void ProgramShaderCache::SetProgramVariables(PCacheEntry &entry) snprintf(name, 8, "samp%d", a); // Still need to get sampler locations since we aren't binding them statically in the shaders - int loc = glGetUniformLocation(entry.prog_id, name); + int loc = glGetUniformLocation(glprogid, name); if (loc != -1) glUniform1i(loc, a); } } -void ProgramShaderCache::SetProgramBindings ( ProgramShaderCache::PCacheEntry& entry ) +void SHADER::SetProgramBindings() { if (g_ActiveConfig.backend_info.bSupportsDualSourceBlend) { // So we do support extended blending // So we need to set a few more things here. // Bind our out locations - glBindFragDataLocationIndexed(entry.prog_id, 0, 0, "ocol0"); - glBindFragDataLocationIndexed(entry.prog_id, 0, 1, "ocol1"); + glBindFragDataLocationIndexed(glprogid, 0, 0, "ocol0"); + glBindFragDataLocationIndexed(glprogid, 0, 1, "ocol1"); } else - glBindFragDataLocation(entry.prog_id, 0, "ocol0"); + glBindFragDataLocation(glprogid, 0, "ocol0"); // Need to set some attribute locations - glBindAttribLocation(entry.prog_id, SHADER_POSITION_ATTRIB, "rawpos"); + glBindAttribLocation(glprogid, SHADER_POSITION_ATTRIB, "rawpos"); - glBindAttribLocation(entry.prog_id, SHADER_POSMTX_ATTRIB, "fposmtx"); + glBindAttribLocation(glprogid, SHADER_POSMTX_ATTRIB, "fposmtx"); - glBindAttribLocation(entry.prog_id, SHADER_COLOR0_ATTRIB, "color0"); - glBindAttribLocation(entry.prog_id, SHADER_COLOR1_ATTRIB, "color1"); + glBindAttribLocation(glprogid, SHADER_COLOR0_ATTRIB, "color0"); + glBindAttribLocation(glprogid, SHADER_COLOR1_ATTRIB, "color1"); - glBindAttribLocation(entry.prog_id, SHADER_NORM0_ATTRIB, "rawnorm0"); - glBindAttribLocation(entry.prog_id, SHADER_NORM1_ATTRIB, "rawnorm1"); - glBindAttribLocation(entry.prog_id, SHADER_NORM2_ATTRIB, "rawnorm2"); + glBindAttribLocation(glprogid, SHADER_NORM0_ATTRIB, "rawnorm0"); + glBindAttribLocation(glprogid, SHADER_NORM1_ATTRIB, "rawnorm1"); + glBindAttribLocation(glprogid, SHADER_NORM2_ATTRIB, "rawnorm2"); for(int i=0; i<8; i++) { char attrib_name[8]; snprintf(attrib_name, 8, "tex%d", i); - glBindAttribLocation(entry.prog_id, SHADER_TEXTURE0_ATTRIB+i, attrib_name); + glBindAttribLocation(glprogid, SHADER_TEXTURE0_ATTRIB+i, attrib_name); } } - -void ProgramShaderCache::SetBothShaders(GLuint PS, GLuint VS) +void SHADER::Bind() { - if(!PS || !VS) { - ERROR_LOG(VIDEO, "tried to bind a zero shader"); - return; - } - - u64 ShaderPair = Create_Pair(PS, VS); - - // program is already bound - if(ShaderPair == CurrentShaderProgram) return; - - PCache::iterator iter = pshaders.find(ShaderPair); - if (iter != pshaders.end()) + if(CurrentProgram != glprogid) { - PCacheEntry &entry = iter->second; - glUseProgram(entry.prog_id); - CurrentProgram = entry.prog_id; - CurrentShaderProgram = ShaderPair; - return; + glUseProgram(glprogid); + CurrentProgram = glprogid; } - - PCacheEntry entry; - entry.Create(PS, VS); - - // Right, the program is created now - // Let's attach everything - glAttachShader(entry.prog_id, entry.vsid); - glAttachShader(entry.prog_id, entry.psid); - - if (g_ActiveConfig.backend_info.bSupportsGLSLCache) - glProgramParameteri(entry.prog_id, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); - - SetProgramBindings(entry); - - glLinkProgram(entry.prog_id); - -#if defined(_DEBUG) || defined(DEBUGFAST) || defined(DEBUG_GLSL) - GLsizei length = 0; - glGetProgramiv(entry.prog_id, GL_INFO_LOG_LENGTH, &length); - if (length > 1) - { - GLsizei charsWritten; - GLchar* infoLog = new GLchar[length]; - glGetProgramInfoLog(entry.prog_id, length, &charsWritten, infoLog); - ERROR_LOG(VIDEO, "Program info log:\n%s", infoLog); - char szTemp[MAX_PATH]; - sprintf(szTemp, "p_%d.txt", entry.prog_id); - FILE *fp = fopen(szTemp, "wb"); - fwrite(infoLog, length, 1, fp); - delete[] infoLog; - - glGetShaderiv(VS, GL_SHADER_SOURCE_LENGTH, &length); - GLchar* src = new GLchar[length]; - glGetShaderSource(VS, length, &charsWritten, src); - fwrite(src, strlen(src), 1, fp); - delete [] src; - - glGetShaderiv(PS, GL_SHADER_SOURCE_LENGTH, &length); - src = new GLchar[length]; - glGetShaderSource(PS, length, &charsWritten, src); - fwrite(src, strlen(src), 1, fp); - delete [] src; - fclose(fp); - } - - GLint linkStatus; - glGetProgramiv(entry.prog_id, GL_LINK_STATUS, &linkStatus); - if (linkStatus != GL_TRUE) - { - // Compile failed - ERROR_LOG(VIDEO, "Program linking failed; see info log"); - - // Don't try to use this shader - glDeleteProgram(entry.prog_id); - return; - } -#endif - - glUseProgram(entry.prog_id); - - SetProgramVariables(entry); - - pshaders[ShaderPair] = entry; - CurrentShaderProgram = ShaderPair; - CurrentProgram = entry.prog_id; } + void ProgramShaderCache::SetMultiPSConstant4fv(unsigned int offset, const float *f, unsigned int count) { s_ubo_dirty = true; @@ -264,9 +181,207 @@ GLuint ProgramShaderCache::GetCurrentProgram(void) return CurrentProgram; } +SHADER* ProgramShaderCache::SetShader ( DSTALPHA_MODE dstAlphaMode, u32 components ) +{ + SHADERUID uid; + GetShaderId(&uid, dstAlphaMode, components); + + // Check if the shader is already set + if (last_entry) + { + if (uid == last_uid) + { + GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); + ValidateShaderIDs(last_entry, dstAlphaMode, components); + last_entry->shader.Bind(); + return &last_entry->shader; + } + } + + last_uid = uid; + + // Check if shader is already in cache + PCache::iterator iter = pshaders.find(uid); + if (iter != pshaders.end()) + { + PCacheEntry *entry = &iter->second; + last_entry = entry; + + GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); + ValidateShaderIDs(entry, dstAlphaMode, components); + last_entry->shader.Bind(); + return &last_entry->shader; + } + + // Make an entry in the table + PCacheEntry& newentry = pshaders[uid]; + last_entry = &newentry; + + const char *vcode = GenerateVertexShaderCode(components, API_OPENGL); + const char *pcode = GeneratePixelShaderCode(dstAlphaMode, API_OPENGL, components); + + if (g_ActiveConfig.bEnableShaderDebugging) + { + GetSafePixelShaderId(&newentry.safe_uid, dstAlphaMode, components); + newentry.shader.strvprog = vcode; + newentry.shader.strpprog = pcode; + } + +#if defined(_DEBUG) || defined(DEBUGFAST) + if (g_ActiveConfig.iLog & CONF_SAVESHADERS) { + static int counter = 0; + char szTemp[MAX_PATH]; + sprintf(szTemp, "%svs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++); + SaveData(szTemp, vcode); + sprintf(szTemp, "%sps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++); + SaveData(szTemp, pcode); + } +#endif + + if (!CompileShader(newentry.shader, vcode, pcode)) { + GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true); + return NULL; + } + + INCSTAT(stats.numPixelShadersCreated); + SETSTAT(stats.numPixelShadersAlive, pshaders.size()); + GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); + + last_entry->shader.Bind(); + return &last_entry->shader; +} + +bool ProgramShaderCache::CompileShader ( SHADER& shader, const char* vcode, const char* pcode ) +{ + GLuint vsid = CompileSingleShader(GL_VERTEX_SHADER, vcode); + GLuint psid = CompileSingleShader(GL_FRAGMENT_SHADER, pcode); + + if(!vsid || !psid) + { + glDeleteShader(vsid); + glDeleteShader(psid); + return false; + } + + GLuint pid = shader.glprogid = glCreateProgram();; + + glAttachShader(pid, vsid); + glAttachShader(pid, psid); + + if (g_ActiveConfig.backend_info.bSupportsGLSLCache) + glProgramParameteri(pid, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); + + shader.SetProgramBindings(); + + glLinkProgram(pid); + + // original shaders aren't needed any more + glDeleteShader(vsid); + glDeleteShader(psid); + +#if defined(_DEBUG) || defined(DEBUGFAST) || defined(DEBUG_GLSL) + GLsizei length = 0; + glGetProgramiv(pid, GL_INFO_LOG_LENGTH, &length); + if (length > 1) + { + GLsizei charsWritten; + GLchar* infoLog = new GLchar[length]; + glGetProgramInfoLog(pid, length, &charsWritten, infoLog); + ERROR_LOG(VIDEO, "Program info log:\n%s", infoLog); + char szTemp[MAX_PATH]; + sprintf(szTemp, "p_%d.txt", pid); + FILE *fp = fopen(szTemp, "wb"); + fwrite(infoLog, length, 1, fp); + delete[] infoLog; + fwrite(vcode, strlen(vcode), 1, fp); + fwrite(pcode, strlen(pcode), 1, fp); + fclose(fp); + } + + GLint linkStatus; + glGetProgramiv(pid, GL_LINK_STATUS, &linkStatus); + if (linkStatus != GL_TRUE) + { + // Compile failed + ERROR_LOG(VIDEO, "Program linking failed; see info log"); + + // Don't try to use this shader + glDeleteProgram(pid); + return false; + } +#endif + + shader.SetProgramVariables(); + + return true; +} + +GLuint ProgramShaderCache::CompileSingleShader (GLuint type, const char* code ) +{ + GLuint result = glCreateShader(type); + + const char *src[] = {code}; + + glShaderSource(result, 1, src, NULL); + glCompileShader(result); +#if defined(_DEBUG) || defined(DEBUGFAST) || defined(DEBUG_GLSL) + GLsizei length = 0; + glGetShaderiv(result, GL_INFO_LOG_LENGTH, &length); + if (length > 1) + { + GLsizei charsWritten; + GLchar* infoLog = new GLchar[length]; + glGetShaderInfoLog(result, length, &charsWritten, infoLog); + ERROR_LOG(VIDEO, "PS Shader info log:\n%s", infoLog); + char szTemp[MAX_PATH]; + sprintf(szTemp, "ps_%d.txt", result); + FILE *fp = fopen(szTemp, "wb"); + fwrite(infoLog, strlen(infoLog), 1, fp); + fwrite(code, strlen(code), 1, fp); + fclose(fp); + delete[] infoLog; + } + + GLint compileStatus; + glGetShaderiv(result, GL_COMPILE_STATUS, &compileStatus); + if (compileStatus != GL_TRUE) + { + // Compile failed + ERROR_LOG(VIDEO, "Shader compilation failed; see info log"); + + // Don't try to use this shader + glDeleteShader(result); + return 0; + } +#endif + (void)GL_REPORT_ERROR(); + return result; +} + + + +void ProgramShaderCache::GetShaderId ( SHADERUID* uid, DSTALPHA_MODE dstAlphaMode, u32 components ) +{ + GetPixelShaderId(&uid->puid, dstAlphaMode, components); + GetVertexShaderId(&uid->vuid, components); +} + +void ProgramShaderCache::GetSafeShaderId ( SHADERUIDSAFE* uid, DSTALPHA_MODE dstAlphaMode, u32 components ) +{ + GetSafePixelShaderId(&uid->puid, dstAlphaMode, components); + GetSafeVertexShaderId(&uid->vuid, components); +} + +void ProgramShaderCache::ValidateShaderIDs ( PCacheEntry *entry, DSTALPHA_MODE dstAlphaMode, u32 components ) +{ + //ValidatePixelShaderIDs(API_OPENGL, entry->safe_uid, entry->shader.strprog, dstAlphaMode, components); +} + + + ProgramShaderCache::PCacheEntry ProgramShaderCache::GetShaderProgram(void) { - return pshaders[CurrentShaderProgram]; + return *last_entry; } void ProgramShaderCache::Init(void) @@ -308,7 +423,7 @@ void ProgramShaderCache::Init(void) } CurrentProgram = 0; - CurrentShaderProgram = 0; + last_entry = NULL; } void ProgramShaderCache::Shutdown(void) @@ -318,7 +433,7 @@ void ProgramShaderCache::Shutdown(void) PCache::iterator iter = pshaders.begin(); for (; iter != pshaders.end(); ++iter) { - g_program_disk_cache.Append(iter->second.uid, iter->second.GetProgram(), iter->second.Size()); + g_program_disk_cache.Append(iter->first, iter->second.GetProgram(), iter->second.Size()); iter->second.FreeProgram(); } @@ -342,4 +457,23 @@ void ProgramShaderCache::Shutdown(void) } } +void ProgramShaderCache::ProgramShaderCacheInserter::Read ( const SHADERUID& key, const u8* value, u32 value_size ) +{ + // The two shaders might not even exist anymore + // But it is fine, no need to worry about that + PCacheEntry entry; + entry.shader.glprogid = glCreateProgram(); + glProgramBinary(entry.shader.glprogid, entry.prog_format, value, value_size); + + GLint success; + glGetProgramiv(entry.shader.glprogid, GL_LINK_STATUS, &success); + + if (success) + { + pshaders[key] = entry; + entry.shader.SetProgramVariables(); + } +} + + } // namespace OGL diff --git a/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.h b/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.h index a173b23095..76df0787e8 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/ProgramShaderCache.h @@ -20,28 +20,63 @@ #include "GLUtil.h" -#include "VertexShaderCache.h" -#include "PixelShaderCache.h" #include "PixelShaderGen.h" #include "VertexShaderGen.h" #include "LinearDiskCache.h" #include "ConfigManager.h" -#ifdef __APPLE__ -#include -using namespace std::tr1; -#else -#include -using namespace std; -#endif namespace OGL { +template +class _SHADERUID +{ +public: + _VERTEXSHADERUID vuid; + _PIXELSHADERUID puid; + + _SHADERUID() {} + + _SHADERUID(const _SHADERUID& r) : vuid(r.vuid), puid(r.puid) {} + + bool operator <(const _SHADERUID& r) const + { + if(puid < r.puid) return true; + if(r.puid < puid) return false; + if(vuid < r.vuid) return true; + return false; + } + + bool operator ==(const _SHADERUID& r) const + { + return puid == r.puid && vuid == r.vuid; + } +}; +typedef _SHADERUID SHADERUID; +typedef _SHADERUID SHADERUIDSAFE; + + const int NUM_UNIFORMS = 19; extern const char *UniformNames[NUM_UNIFORMS]; -u64 Create_Pair(u32 key1, u32 key2); -void Get_Pair(u64 key, u32 *key1, u32 *key2); + +struct SHADER +{ + SHADER() : glprogid(0) { } + void Destroy() + { + glDeleteProgram(glprogid); + glprogid = 0; + } + GLuint glprogid; // opengl program id + + std::string strvprog, strpprog; + GLint UniformLocations[NUM_UNIFORMS]; + + void SetProgramVariables(); + void SetProgramBindings(); + void Bind(); +}; class ProgramShaderCache { @@ -49,39 +84,27 @@ public: struct PCacheEntry { - GLuint prog_id; + SHADER shader; + PIXELSHADERUIDSAFE safe_uid; + static GLenum prog_format; u8 *binary; GLint binary_size; - GLuint vsid, psid; - u64 uid; - GLint UniformLocations[NUM_UNIFORMS]; + + PCacheEntry() :binary(NULL), binary_size(0) { } - PCacheEntry() : prog_id(0), binary(NULL), binary_size(0), vsid(0), psid(0) { } - - ~PCacheEntry() - { - FreeProgram(); - } - - void Create(const GLuint pix_id, const GLuint vert_id) - { - psid = pix_id; - vsid = vert_id; - uid = Create_Pair(psid, vsid); - prog_id = glCreateProgram(); - } + ~PCacheEntry() {} void Destroy() { - glDeleteProgram(prog_id); - prog_id = 0; + shader.Destroy(); + FreeProgram(); } void UpdateSize() { if (binary_size == 0) - glGetProgramiv(prog_id, GL_PROGRAM_BINARY_LENGTH, &binary_size); + glGetProgramiv(shader.glprogid, GL_PROGRAM_BINARY_LENGTH, &binary_size); } // No idea how necessary this is @@ -103,7 +126,7 @@ public: UpdateSize(); FreeProgram(); binary = new u8[binary_size]; - glGetProgramBinary(prog_id, binary_size, NULL, &prog_format, binary); + glGetProgramBinary(shader.glprogid, binary_size, NULL, &prog_format, binary); return binary; } @@ -121,8 +144,14 @@ public: }; static PCacheEntry GetShaderProgram(void); - static void SetBothShaders(GLuint PS, GLuint VS); static GLuint GetCurrentProgram(void); + static SHADER* SetShader(DSTALPHA_MODE dstAlphaMode, u32 components); + static void GetShaderId(SHADERUID *uid, DSTALPHA_MODE dstAlphaMode, u32 components); + static void GetSafeShaderId(SHADERUIDSAFE *uid, DSTALPHA_MODE dstAlphaMode, u32 components); + static void ValidateShaderIDs(PCacheEntry *entry, DSTALPHA_MODE dstAlphaMode, u32 components); + + static bool CompileShader(SHADER &shader, const char* vcode, const char* pcode); + static GLuint CompileSingleShader(GLuint type, const char *code); static void SetMultiPSConstant4fv(unsigned int offset, const float *f, unsigned int count); static void SetMultiVSConstant4fv(unsigned int offset, const float *f, unsigned int count); @@ -132,44 +161,22 @@ public: static void Shutdown(void); private: - class ProgramShaderCacheInserter : public LinearDiskCacheReader + class ProgramShaderCacheInserter : public LinearDiskCacheReader { public: - void Read(const u64 &key, const u8 *value, u32 value_size) - { - // The two shaders might not even exist anymore - // But it is fine, no need to worry about that - PCacheEntry entry; - u32 key1, key2; - Get_Pair(key, &key1, &key2); - entry.Create(key1, key2); - - glProgramBinary(entry.prog_id, entry.prog_format, value, value_size); - - GLint success; - glGetProgramiv(entry.prog_id, GL_LINK_STATUS, &success); - - if (success) - { - pshaders[key] = entry; - glUseProgram(entry.prog_id); - SetProgramVariables(entry); - } - } + void Read(const SHADERUID &key, const u8 *value, u32 value_size); }; - typedef unordered_map PCache; + typedef std::map PCache; static PCache pshaders; - static GLuint CurrentProgram; - static u64 CurrentShaderProgram; + static PCacheEntry* last_entry; + static SHADERUID last_uid; static GLintptr s_vs_data_offset; static u8 *s_ubo_buffer; static u32 s_ubo_buffer_size; static bool s_ubo_dirty; - static void SetProgramVariables(PCacheEntry &entry); - static void SetProgramBindings(PCacheEntry &entry); }; } // namespace OGL diff --git a/Source/Plugins/Plugin_VideoOGL/Src/RasterFont.cpp b/Source/Plugins/Plugin_VideoOGL/Src/RasterFont.cpp index f7afb63c9c..19e36b0774 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/RasterFont.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/RasterFont.cpp @@ -18,9 +18,7 @@ #include "GLUtil.h" #include "RasterFont.h" -#include "PixelShaderCache.h" #include "ProgramShaderCache.h" -#include "VertexShaderCache.h" // globals namespace OGL { @@ -149,9 +147,7 @@ static const char *s_fragmentShaderSrc = " ocol0 = texture(samp8,uv0) * color;\n" "}\n"; - -static FRAGMENTSHADER s_fragmentShader; -static VERTEXSHADER s_vertexShader; +static SHADER s_shader; RasterFont::RasterFont() { @@ -174,14 +170,11 @@ RasterFont::RasterFont() delete [] texture_data; // generate shader - VertexShaderCache::CompileVertexShader(s_vertexShader, s_vertexShaderSrc); - PixelShaderCache::CompilePixelShader(s_fragmentShader, s_fragmentShaderSrc); - ProgramShaderCache::SetBothShaders(s_fragmentShader.glprogid, s_vertexShader.glprogid); - GLuint shader_program = ProgramShaderCache::GetCurrentProgram(); + ProgramShaderCache::CompileShader(s_shader, s_vertexShaderSrc, s_fragmentShaderSrc); // bound uniforms - glUniform2f(glGetUniformLocation(shader_program,"charSize"), 1.0f / GLfloat(char_count), 1.0f); - uniform_color_id = glGetUniformLocation(shader_program,"color"); + glUniform2f(glGetUniformLocation(s_shader.glprogid,"charSize"), 1.0f / GLfloat(char_count), 1.0f); + uniform_color_id = glGetUniformLocation(s_shader.glprogid,"color"); glUniform4f(uniform_color_id, 1.0f, 1.0f, 1.0f, 1.0f); cached_color = -1; @@ -201,8 +194,7 @@ RasterFont::~RasterFont() glDeleteTextures(1, &texture); glDeleteBuffers(1, &VBO); glDeleteVertexArrays(1, &VAO); - s_fragmentShader.Destroy(); - s_vertexShader.Destroy(); + s_shader.Destroy(); } void RasterFont::printMultilineText(const char *text, double start_x, double start_y, double z, int bbWidth, int bbHeight, u32 color) @@ -280,7 +272,7 @@ void RasterFont::printMultilineText(const char *text, double start_x, double sta delete [] vertices; - ProgramShaderCache::SetBothShaders(s_fragmentShader.glprogid, s_vertexShader.glprogid); + s_shader.Bind(); if(color != cached_color) { glUniform4f(uniform_color_id, GLfloat((color>>16)&0xff)/255.f,GLfloat((color>>8)&0xff)/255.f,GLfloat((color>>0)&0xff)/255.f,GLfloat((color>>24)&0xff)/255.f); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index d1abe7ffe2..f311cc62ad 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -43,10 +43,8 @@ #include "RasterFont.h" #include "VertexShaderGen.h" #include "DLCache.h" -#include "PixelShaderCache.h" #include "PixelShaderManager.h" #include "ProgramShaderCache.h" -#include "VertexShaderCache.h" #include "VertexShaderManager.h" #include "VertexLoaderManager.h" #include "VertexLoader.h" @@ -107,8 +105,7 @@ namespace OGL static int s_fps = 0; static GLuint s_ShowEFBCopyRegions_VBO = 0; static GLuint s_ShowEFBCopyRegions_VAO = 0; -static FRAGMENTSHADER s_ShowEFBCopyRegions_PS; -static VERTEXSHADER s_ShowEFBCopyRegions_VS; +static SHADER s_ShowEFBCopyRegions; static RasterFont* s_pfont = NULL; @@ -433,23 +430,14 @@ void Renderer::Shutdown() delete s_pfont; s_pfont = 0; - s_ShowEFBCopyRegions_PS.Destroy(); - s_ShowEFBCopyRegions_VS.Destroy(); + s_ShowEFBCopyRegions.Destroy(); } void Renderer::Init() { s_pfont = new RasterFont(); - PixelShaderCache::CompilePixelShader(s_ShowEFBCopyRegions_PS, - "#version 130\n" - "in vec4 c;\n" - "out vec4 ocol0;\n" - "void main(void) {\n" - " ocol0 = c;\n" - "}\n" - ); - VertexShaderCache::CompileVertexShader(s_ShowEFBCopyRegions_VS, + ProgramShaderCache::CompileShader(s_ShowEFBCopyRegions, "#version 130\n" "in vec2 rawpos;\n" "in vec3 color0;\n" @@ -457,8 +445,13 @@ void Renderer::Init() "void main(void) {\n" " gl_Position = vec4(rawpos,0,1);\n" " c = vec4(color0, 1.0);\n" - "}\n" - ); + "}\n", + "#version 130\n" + "in vec4 c;\n" + "out vec4 ocol0;\n" + "void main(void) {\n" + " ocol0 = c;\n" + "}\n"); // creating buffers glGenBuffers(1, &s_ShowEFBCopyRegions_VBO); @@ -603,7 +596,7 @@ void Renderer::DrawDebugInfo() } glUnmapBuffer(GL_ARRAY_BUFFER); - ProgramShaderCache::SetBothShaders(s_ShowEFBCopyRegions_PS.glprogid, s_ShowEFBCopyRegions_VS.glprogid); + s_ShowEFBCopyRegions.Bind(); glBindVertexArray( s_ShowEFBCopyRegions_VAO ); glDrawArrays(GL_LINES, 0, stats.efb_regions.size() * 2*6); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp index ae25c33a57..0aa47430dc 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp @@ -42,7 +42,6 @@ #include "HW/Memmap.h" #include "ImageWrite.h" #include "MemoryUtil.h" -#include "PixelShaderCache.h" #include "ProgramShaderCache.h" #include "PixelShaderManager.h" #include "Render.h" @@ -57,13 +56,12 @@ namespace OGL { -static FRAGMENTSHADER s_ColorMatrixProgram; -static FRAGMENTSHADER s_DepthMatrixProgram; +static SHADER s_ColorMatrixProgram; +static SHADER s_DepthMatrixProgram; static GLuint s_ColorMatrixUniform; static GLuint s_DepthMatrixUniform; static u32 s_ColorCbufid; static u32 s_DepthCbufid; -static VERTEXSHADER s_vProgram; static u32 s_Textures[8]; static u32 s_ActiveTexture; @@ -335,12 +333,12 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo glViewport(0, 0, virtual_width, virtual_height); if(srcFormat == PIXELFMT_Z24) { - ProgramShaderCache::SetBothShaders(s_DepthMatrixProgram.glprogid, s_vProgram.glprogid); + s_DepthMatrixProgram.Bind(); if(s_DepthCbufid != cbufid) glUniform4fv(s_DepthMatrixUniform, 5, colmat); s_DepthCbufid = cbufid; } else { - ProgramShaderCache::SetBothShaders(s_ColorMatrixProgram.glprogid, s_vProgram.glprogid); + s_ColorMatrixProgram.Bind(); if(s_ColorCbufid != cbufid) glUniform4fv(s_ColorMatrixUniform, 7, colmat); s_ColorCbufid = cbufid; @@ -499,11 +497,6 @@ TextureCache::TextureCache() " Temp1.w = dot(Temp0, colmat[3]);\n" " ocol0 = Temp1 + colmat[4];\n" "}\n"; - if (!PixelShaderCache::CompilePixelShader(s_ColorMatrixProgram, pColorMatrixProg)) - { - ERROR_LOG(VIDEO, "Failed to create color matrix fragment program"); - s_ColorMatrixProgram.Destroy(); - } const char *pDepthMatrixProg = "#version 130\n" @@ -538,11 +531,6 @@ TextureCache::TextureCache() " ocol0 = R1 * colmat[4];\n" "}\n"; - if (!PixelShaderCache::CompilePixelShader(s_DepthMatrixProgram, pDepthMatrixProg)) - { - ERROR_LOG(VIDEO, "Failed to create depth matrix fragment program"); - s_DepthMatrixProgram.Destroy(); - } const char *VProgram = "#version 130\n" @@ -554,13 +542,12 @@ TextureCache::TextureCache() " uv0 = tex0;\n" " gl_Position = vec4(rawpos,0,1);\n" "}\n"; - if (!VertexShaderCache::CompileVertexShader(s_vProgram, VProgram)) - ERROR_LOG(VIDEO, "Failed to create texture converter vertex program."); + + ProgramShaderCache::CompileShader(s_ColorMatrixProgram, VProgram, pColorMatrixProg); + ProgramShaderCache::CompileShader(s_DepthMatrixProgram, VProgram, pDepthMatrixProg); - ProgramShaderCache::SetBothShaders(s_ColorMatrixProgram.glprogid, s_vProgram.glprogid); - s_ColorMatrixUniform = glGetUniformLocation(ProgramShaderCache::GetCurrentProgram(), "colmat"); - ProgramShaderCache::SetBothShaders(s_DepthMatrixProgram.glprogid, s_vProgram.glprogid); - s_DepthMatrixUniform = glGetUniformLocation(ProgramShaderCache::GetCurrentProgram(), "colmat"); + s_ColorMatrixUniform = glGetUniformLocation(s_ColorMatrixProgram.glprogid, "colmat"); + s_DepthMatrixUniform = glGetUniformLocation(s_DepthMatrixProgram.glprogid, "colmat"); s_ColorCbufid = -1; s_DepthCbufid = -1; @@ -574,7 +561,6 @@ TextureCache::~TextureCache() { s_ColorMatrixProgram.Destroy(); s_DepthMatrixProgram.Destroy(); - s_vProgram.Destroy(); for(std::map::iterator it = s_VBO.begin(); it != s_VBO.end(); it++) { glDeleteBuffers(1, &it->second.vbo); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp index 1dad409a64..6914f00379 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp @@ -23,7 +23,6 @@ #include "TextureConverter.h" #include "TextureConversionShader.h" #include "TextureCache.h" -#include "PixelShaderCache.h" #include "ProgramShaderCache.h" #include "VertexShaderManager.h" #include "FramebufferManager.h" @@ -51,13 +50,12 @@ static GLuint s_dstRenderBuffer = 0; // for encoding to RAM const int renderBufferWidth = 1024; const int renderBufferHeight = 1024; -static FRAGMENTSHADER s_rgbToYuyvProgram; -static FRAGMENTSHADER s_yuyvToRgbProgram; -static VERTEXSHADER s_vProgram; +static SHADER s_rgbToYuyvProgram; +static SHADER s_yuyvToRgbProgram; // Not all slots are taken - but who cares. const u32 NUM_ENCODING_PROGRAMS = 64; -static FRAGMENTSHADER s_encodingPrograms[NUM_ENCODING_PROGRAMS]; +static SHADER s_encodingPrograms[NUM_ENCODING_PROGRAMS]; static GLuint s_encode_VBO = 0; static GLuint s_encode_VAO = 0; @@ -67,6 +65,17 @@ static TargetRectangle s_cached_sourceRc; static int s_cached_srcWidth = 0; static int s_cached_srcHeight = 0; +static const char *VProgram = + "#version 130\n" + "in vec2 rawpos;\n" + "in vec2 tex0;\n" + "out vec2 uv0;\n" + "void main()\n" + "{\n" + " uv0 = tex0;\n" + " gl_Position = vec4(rawpos,0,1);\n" + "}\n"; + void CreatePrograms() { // Output is BGRA because that is slightly faster than RGBA. @@ -87,8 +96,6 @@ void CreatePrograms() " vec4 const3 = vec4(0.0625,0.5,0.0625f,0.5);\n" " ocol0 = vec4(dot(c1,y_const),dot(c01,u_const),dot(c0,y_const),dot(c01, v_const)) + const3;\n" "}\n"; - if (!PixelShaderCache::CompilePixelShader(s_rgbToYuyvProgram, FProgramRgbToYuyv)) - ERROR_LOG(VIDEO, "Failed to create RGB to YUYV fragment program."); const char *FProgramYuyvToRgb = "#version 130\n" @@ -109,24 +116,12 @@ void CreatePrograms() " yComp + (2.018f * uComp),\n" " 1.0f);\n" "}\n"; - if (!PixelShaderCache::CompilePixelShader(s_yuyvToRgbProgram, FProgramYuyvToRgb)) - ERROR_LOG(VIDEO, "Failed to create YUYV to RGB fragment program."); - - const char *VProgram = - "#version 130\n" - "in vec2 rawpos;\n" - "in vec2 tex0;\n" - "out vec2 uv0;\n" - "void main()\n" - "{\n" - " uv0 = tex0;\n" - " gl_Position = vec4(rawpos,0,1);\n" - "}\n"; - if (!VertexShaderCache::CompileVertexShader(s_vProgram, VProgram)) - ERROR_LOG(VIDEO, "Failed to create texture converter vertex program."); + + ProgramShaderCache::CompileShader(s_rgbToYuyvProgram, VProgram, FProgramRgbToYuyv); + ProgramShaderCache::CompileShader(s_yuyvToRgbProgram, VProgram, FProgramYuyvToRgb); } -FRAGMENTSHADER &GetOrCreateEncodingShader(u32 format) +SHADER &GetOrCreateEncodingShader(u32 format) { if (format > NUM_ENCODING_PROGRAMS) { @@ -149,9 +144,7 @@ FRAGMENTSHADER &GetOrCreateEncodingShader(u32 format) } #endif - if (!PixelShaderCache::CompilePixelShader(s_encodingPrograms[format], shader)) { - ERROR_LOG(VIDEO, "Failed to create encoding fragment program"); - } + ProgramShaderCache::CompileShader(s_encodingPrograms[format], VProgram, shader); } return s_encodingPrograms[format]; } @@ -213,7 +206,6 @@ void Shutdown() s_rgbToYuyvProgram.Destroy(); s_yuyvToRgbProgram.Destroy(); - s_vProgram.Destroy(); for (unsigned int i = 0; i < NUM_ENCODING_PROGRAMS; i++) s_encodingPrograms[i].Destroy(); @@ -325,9 +317,7 @@ int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer, if (copyfmt > GX_TF_RGBA8 || (copyfmt < GX_TF_RGB565 && !bIsIntensityFmt)) format |= _GX_TF_CTF; - FRAGMENTSHADER& texconv_shader = GetOrCreateEncodingShader(format); - if (texconv_shader.glprogid == 0) - return 0; + SHADER& texconv_shader = GetOrCreateEncodingShader(format); u8 *dest_ptr = Memory::GetPointer(address); @@ -344,8 +334,6 @@ int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer, // extra pixels are copied but not displayed in the resulting texture s32 expandedWidth = (width + blkW) & (~blkW); s32 expandedHeight = (height + blkH) & (~blkH); - - ProgramShaderCache::SetBothShaders(texconv_shader.glprogid, s_vProgram.glprogid); float sampleStride = bScaleByHalf ? 2.f : 1.f; @@ -355,7 +343,9 @@ int EncodeToRamFromTexture(u32 address,GLuint source_texture, bool bFromZBuffer, (float)expandedWidth, (float)Renderer::EFBToScaledY(expandedHeight)-1, (float)Renderer::EFBToScaledX(source.left), (float)Renderer::EFBToScaledY(EFB_HEIGHT - source.top - expandedHeight) }; - glUniform4fv(ProgramShaderCache::GetShaderProgram().UniformLocations[C_COLORS], 2, params); + + texconv_shader.Bind(); + glUniform4fv(texconv_shader.UniformLocations[C_COLORS], 2, params); TargetRectangle scaledSource; scaledSource.top = 0; @@ -379,7 +369,7 @@ void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* des { g_renderer->ResetAPIState(); - ProgramShaderCache::SetBothShaders(s_rgbToYuyvProgram.glprogid, s_vProgram.glprogid); + s_rgbToYuyvProgram.Bind(); EncodeToRamUsingShader(srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false); FramebufferManager::SetFramebuffer(0); @@ -431,7 +421,7 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destRender } glViewport(0, 0, srcWidth, srcHeight); - ProgramShaderCache::SetBothShaders(s_yuyvToRgbProgram.glprogid, s_vProgram.glprogid); + s_yuyvToRgbProgram.Bind(); GL_REPORT_ERRORD(); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index 59a78fa1a2..367f946caf 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -29,9 +29,7 @@ #include "ImageWrite.h" #include "BPMemory.h" #include "TextureCache.h" -#include "PixelShaderCache.h" #include "PixelShaderManager.h" -#include "VertexShaderCache.h" #include "VertexShaderManager.h" #include "ProgramShaderCache.h" #include "VertexShaderGen.h" @@ -246,28 +244,23 @@ void VertexManager::vFlush() bool dualSourcePossible = g_ActiveConfig.backend_info.bSupportsDualSourceBlend; // finally bind - FRAGMENTSHADER* ps; if (dualSourcePossible) { if (useDstAlpha) { // If host supports GL_ARB_blend_func_extended, we can do dst alpha in // the same pass as regular rendering. - ps = PixelShaderCache::SetShader(DSTALPHA_DUAL_SOURCE_BLEND, g_nativeVertexFmt->m_components); + ProgramShaderCache::SetShader(DSTALPHA_DUAL_SOURCE_BLEND, g_nativeVertexFmt->m_components); } else { - ps = PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components); + ProgramShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components); } } else { - ps = PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components); + ProgramShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components); } - VERTEXSHADER* vs = VertexShaderCache::SetShader(g_nativeVertexFmt->m_components); - - if(ps && vs) - ProgramShaderCache::SetBothShaders(ps->glprogid, vs->glprogid); // set global constants VertexShaderManager::SetConstants(); @@ -284,9 +277,7 @@ void VertexManager::vFlush() // run through vertex groups again to set alpha if (useDstAlpha && !dualSourcePossible) { - ps = PixelShaderCache::SetShader(DSTALPHA_ALPHA_PASS,g_nativeVertexFmt->m_components); - if(ps && vs) - ProgramShaderCache::SetBothShaders(ps->glprogid, vs->glprogid); + ProgramShaderCache::SetShader(DSTALPHA_ALPHA_PASS,g_nativeVertexFmt->m_components); if (!g_ActiveConfig.backend_info.bSupportsGLSLUBO) { // Need to set these again, if we don't support UBO diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp index 37a7b82485..038021c490 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp @@ -27,7 +27,6 @@ #include "VertexShaderGen.h" #include "VertexShaderManager.h" #include "ProgramShaderCache.h" -#include "VertexShaderCache.h" #include "VertexManager.h" #include "VertexLoader.h" #include "XFMemory.h" @@ -38,122 +37,6 @@ namespace OGL { -VertexShaderCache::VSCache VertexShaderCache::vshaders; -GLuint VertexShaderCache::CurrentShader; -bool VertexShaderCache::ShaderEnabled; - -VertexShaderCache::VSCacheEntry* VertexShaderCache::last_entry = NULL; -VERTEXSHADERUID VertexShaderCache::last_uid; - -void VertexShaderCache::Init() -{ - ShaderEnabled = true; - CurrentShader = 0; - last_entry = NULL; -} - -void VertexShaderCache::Shutdown() -{ - for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end(); ++iter) - iter->second.Destroy(); - vshaders.clear(); -} - -VERTEXSHADER* VertexShaderCache::SetShader(u32 components) -{ - VERTEXSHADERUID uid; - GetVertexShaderId(&uid, components); - if (last_entry) - { - if (uid == last_uid) - { - GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true); - ValidateVertexShaderIDs(API_OPENGL, vshaders[uid].safe_uid, vshaders[uid].shader.strprog, components); - return &last_entry->shader; - } - } - - last_uid = uid; - - VSCache::iterator iter = vshaders.find(uid); - if (iter != vshaders.end()) - { - VSCacheEntry &entry = iter->second; - last_entry = &entry; - - GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true); - ValidateVertexShaderIDs(API_OPENGL, entry.safe_uid, entry.shader.strprog, components); - return &last_entry->shader; - } - - // Make an entry in the table - VSCacheEntry& entry = vshaders[uid]; - last_entry = &entry; - const char *code = GenerateVertexShaderCode(components, API_OPENGL); - GetSafeVertexShaderId(&entry.safe_uid, components); - -#if defined(_DEBUG) || defined(DEBUGFAST) - if (g_ActiveConfig.iLog & CONF_SAVESHADERS && code) { - static int counter = 0; - char szTemp[MAX_PATH]; - sprintf(szTemp, "%svs_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), counter++); - - SaveData(szTemp, code); - } -#endif - - if (!code || !VertexShaderCache::CompileVertexShader(entry.shader, code)) { - GFX_DEBUGGER_PAUSE_AT(NEXT_ERROR, true); - return NULL; - } - - INCSTAT(stats.numVertexShadersCreated); - SETSTAT(stats.numVertexShadersAlive, vshaders.size()); - GFX_DEBUGGER_PAUSE_AT(NEXT_VERTEX_SHADER_CHANGE, true); - return &last_entry->shader; -} - -bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram) -{ - GLuint result = glCreateShader(GL_VERTEX_SHADER); - - glShaderSource(result, 1, &pstrprogram, NULL); - glCompileShader(result); -#if defined(_DEBUG) || defined(DEBUGFAST) || defined(DEBUG_GLSL) - GLsizei length = 0; - glGetShaderiv(result, GL_INFO_LOG_LENGTH, &length); - if (length > 1) - { - GLsizei charsWritten; - GLchar* infoLog = new GLchar[length]; - glGetShaderInfoLog(result, length, &charsWritten, infoLog); - ERROR_LOG(VIDEO, "VS Shader info log:\n%s", infoLog); - char szTemp[MAX_PATH]; - sprintf(szTemp, "vs_%d.txt", result); - FILE *fp = fopen(szTemp, "wb"); - fwrite(infoLog, strlen(infoLog), 1, fp); - fwrite(pstrprogram, strlen(pstrprogram), 1, fp); - fclose(fp); - delete[] infoLog; - } - - GLint compileStatus; - glGetShaderiv(result, GL_COMPILE_STATUS, &compileStatus); - if (compileStatus != GL_TRUE) - { - // Compile failed - ERROR_LOG(VIDEO, "Shader compilation failed; see info log"); - - // Don't try to use this shader - glDeleteShader(result); - return false; - } -#endif - (void)GL_REPORT_ERROR(); - vs.glprogid = result; - return true; -} - void SetVSConstant4fvByName(const char * name, unsigned int offset, const float *f, const unsigned int count = 1) { ProgramShaderCache::PCacheEntry tmp = ProgramShaderCache::GetShaderProgram(); @@ -161,11 +44,11 @@ void SetVSConstant4fvByName(const char * name, unsigned int offset, const float { if (!strcmp(name, UniformNames[a])) { - if (tmp.UniformLocations[a] == -1) + if (tmp.shader.UniformLocations[a] == -1) return; else { - glUniform4fv(tmp.UniformLocations[a] + offset, count, f); + glUniform4fv(tmp.shader.UniformLocations[a] + offset, count, f); return; } } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.h b/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.h deleted file mode 100644 index 9fd2a8ee9f..0000000000 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (C) 2003 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#ifndef _VERTEXSHADERCACHE_H_ -#define _VERTEXSHADERCACHE_H_ - -#include -#include - -#include "BPMemory.h" -#include "VertexShaderGen.h" - -namespace OGL -{ - -struct VERTEXSHADER -{ - VERTEXSHADER() : glprogid(0) {} - void Destroy() - { - glDeleteShader(glprogid); - glprogid = 0; - } - GLuint glprogid; // opengl program id - - std::string strprog; -}; - -class VertexShaderCache -{ - struct VSCacheEntry - { - VERTEXSHADER shader; - VERTEXSHADERUIDSAFE safe_uid; - VSCacheEntry() {} - void Destroy() { - shader.Destroy(); - } - }; - - typedef std::map VSCache; - - static VSCache vshaders; - - static VSCacheEntry* last_entry; - static VERTEXSHADERUID last_uid; - - static GLuint CurrentShader; - static bool ShaderEnabled; - -public: - static void Init(); - static void Shutdown(); - - static VERTEXSHADER* SetShader(u32 components); - static bool CompileVertexShader(VERTEXSHADER& ps, const char* pstrprogram); - -}; -} // namespace OGL - -#endif // _VERTEXSHADERCACHE_H_ diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp index 51f44ec0c5..efa13eff76 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp @@ -79,9 +79,7 @@ Make AA apply instantly during gameplay if possible #include "VertexLoader.h" #include "VertexLoaderManager.h" #include "VertexManager.h" -#include "PixelShaderCache.h" #include "PixelShaderManager.h" -#include "VertexShaderCache.h" #include "VertexShaderManager.h" #include "ProgramShaderCache.h" #include "CommandProcessor.h" @@ -194,9 +192,7 @@ void VideoBackend::Video_Prepare() g_vertex_manager = new VertexManager; Fifo_Init(); // must be done before OpcodeDecoder_Init() OpcodeDecoder_Init(); - VertexShaderCache::Init(); VertexShaderManager::Init(); - PixelShaderCache::Init(); PixelShaderManager::Init(); ProgramShaderCache::Init(); g_texture_cache = new TextureCache; @@ -232,10 +228,8 @@ void VideoBackend::Shutdown() delete g_texture_cache; g_texture_cache = NULL; ProgramShaderCache::Shutdown(); - VertexShaderCache::Shutdown(); VertexShaderManager::Shutdown(); PixelShaderManager::Shutdown(); - PixelShaderCache::Shutdown(); delete g_vertex_manager; g_vertex_manager = NULL; OpcodeDecoder_Shutdown();