gsdx-ogl: improve the shader program management

* keep a reference of program/pipeline created to ease the deletion
* extend a bit the API to support multiple pipeline

Final goal will be to use a pre link pipeline for SW shaders. And uses
the default pipeline for HW shaders.
This commit is contained in:
Gregory Hainaut 2016-04-10 17:05:33 +02:00
parent 395e2f31d0
commit 95e3dcb448
6 changed files with 42 additions and 32 deletions

View File

@ -54,6 +54,7 @@ namespace GLState {
GLuint ps; GLuint ps;
GLuint gs; GLuint gs;
GLuint vs; GLuint vs;
GLuint pipeline;
void Clear() { void Clear() {
fbo = 0; fbo = 0;
@ -89,5 +90,6 @@ namespace GLState {
ps = 0; ps = 0;
gs = 0; gs = 0;
vs = 0; vs = 0;
pipeline = 0;
} }
} }

View File

@ -56,6 +56,7 @@ namespace GLState {
extern GLuint ps; extern GLuint ps;
extern GLuint gs; extern GLuint gs;
extern GLuint vs; extern GLuint vs;
extern GLuint pipeline;
extern void Clear(); extern void Clear();
} }

View File

@ -92,38 +92,27 @@ GSDeviceOGL::~GSDeviceOGL()
delete (m_va); delete (m_va);
// Clean m_merge_obj // Clean m_merge_obj
for (size_t i = 0; i < countof(m_merge_obj.ps); i++)
m_shader->Delete(m_merge_obj.ps[i]);
delete (m_merge_obj.cb); delete (m_merge_obj.cb);
// Clean m_interlace // Clean m_interlace
for (size_t i = 0; i < countof(m_interlace.ps); i++)
m_shader->Delete(m_interlace.ps[i]);
delete (m_interlace.cb); delete (m_interlace.cb);
// Clean m_convert // Clean m_convert
m_shader->Delete(m_convert.vs);
for (size_t i = 0; i < countof(m_convert.ps); i++)
m_shader->Delete(m_convert.ps[i]);
delete m_convert.dss; delete m_convert.dss;
delete m_convert.dss_write; delete m_convert.dss_write;
delete m_convert.cb; delete m_convert.cb;
// Clean m_fxaa // Clean m_fxaa
delete m_fxaa.cb; delete m_fxaa.cb;
m_shader->Delete(m_fxaa.ps);
// Clean m_shaderfx // Clean m_shaderfx
delete m_shaderfx.cb; delete m_shaderfx.cb;
m_shader->Delete(m_shaderfx.ps);
// Clean m_date // Clean m_date
delete m_date.dss; delete m_date.dss;
// Clean shadeboost // Clean shadeboost
delete m_shadeboost.cb; delete m_shadeboost.cb;
m_shader->Delete(m_shadeboost.ps);
// Clean various opengl allocation // Clean various opengl allocation
glDeleteFramebuffers(1, &m_fbo); glDeleteFramebuffers(1, &m_fbo);
@ -133,11 +122,6 @@ GSDeviceOGL::~GSDeviceOGL()
delete m_vs_cb; delete m_vs_cb;
delete m_ps_cb; delete m_ps_cb;
glDeleteSamplers(1, &m_palette_ss); glDeleteSamplers(1, &m_palette_ss);
m_shader->Delete(m_apitrace);
for (uint32 key = 0; key < countof(m_vs); key++) m_shader->Delete(m_vs[key]);
for (uint32 key = 0; key < countof(m_gs); key++) m_shader->Delete(m_gs[key]);
for (auto it = m_ps.begin(); it != m_ps.end() ; it++) m_shader->Delete(it->second);
m_ps.clear(); m_ps.clear();
@ -744,7 +728,6 @@ void GSDeviceOGL::SelfShaderTest()
GLuint p = CompilePS(sel); \ GLuint p = CompilePS(sel); \
nb_shader++; \ nb_shader++; \
perf += m_shader->DumpAsm(file, p); \ perf += m_shader->DumpAsm(file, p); \
m_shader->Delete(p); \
} while(0); } while(0);
#define PRINT_TEST(s) \ #define PRINT_TEST(s) \
@ -1025,7 +1008,7 @@ void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture
GSVector2i ds = dTex->GetSize(); GSVector2i ds = dTex->GetSize();
m_shader->Pipeline(m_convert.vs, 0, ps); m_shader->BindPipeline(m_convert.vs, 0, ps);
// ************************************ // ************************************
// om // om
@ -1263,7 +1246,7 @@ void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* ver
ClearStencil(ds, 0); ClearStencil(ds, 0);
m_shader->Pipeline(m_convert.vs, 0, m_convert.ps[datm ? ShaderConvert_DATM_1 : ShaderConvert_DATM_0]); m_shader->BindPipeline(m_convert.vs, 0, m_convert.ps[datm ? ShaderConvert_DATM_1 : ShaderConvert_DATM_0]);
// om // om

View File

@ -27,16 +27,31 @@ GSShaderOGL::GSShaderOGL(bool debug) :
m_pipeline(0), m_pipeline(0),
m_debug_shader(debug) m_debug_shader(debug)
{ {
glCreateProgramPipelines(1, &m_pipeline); // Create a default pipeline
glBindProgramPipeline(m_pipeline); m_pipeline = LinkPipeline(0, 0, 0);
BindPipeline(m_pipeline);
} }
GSShaderOGL::~GSShaderOGL() GSShaderOGL::~GSShaderOGL()
{ {
glDeleteProgramPipelines(1, &m_pipeline); for (auto p : m_prog_to_delete) glDeleteProgram(p);
glDeleteProgramPipelines(m_pipe_to_delete.size(), &m_pipe_to_delete[0]);
} }
void GSShaderOGL::Pipeline(GLuint vs, GLuint gs, GLuint ps) GLuint GSShaderOGL::LinkPipeline(GLuint vs, GLuint gs, GLuint ps)
{
GLuint p;
glCreateProgramPipelines(1, &p);
glUseProgramStages(p, GL_VERTEX_SHADER_BIT, vs);
glUseProgramStages(p, GL_GEOMETRY_SHADER_BIT, gs);
glUseProgramStages(p, GL_FRAGMENT_SHADER_BIT, ps);
m_pipe_to_delete.push_back(p);
return p;
}
void GSShaderOGL::BindPipeline(GLuint vs, GLuint gs, GLuint ps)
{ {
if (GLState::vs != vs) if (GLState::vs != vs)
{ {
@ -60,6 +75,14 @@ void GSShaderOGL::Pipeline(GLuint vs, GLuint gs, GLuint ps)
} }
} }
void GSShaderOGL::BindPipeline(GLuint pipe)
{
if (GLState::pipeline != pipe) {
GLState::pipeline = pipe;
glBindProgramPipeline(pipe);
}
}
bool GSShaderOGL::ValidateProgram(GLuint p) bool GSShaderOGL::ValidateProgram(GLuint p)
{ {
if (!m_debug_shader) return true; if (!m_debug_shader) return true;
@ -182,6 +205,9 @@ GLuint GSShaderOGL::Compile(const std::string& glsl_file, const std::string& ent
fprintf(stderr, "\n%s", macro_sel.c_str()); fprintf(stderr, "\n%s", macro_sel.c_str());
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
m_prog_to_delete.push_back(program);
return program; return program;
} }
@ -243,8 +269,3 @@ int GSShaderOGL::DumpAsm(const std::string& file, GLuint p)
return instructions; return instructions;
} }
void GSShaderOGL::Delete(GLuint s)
{
glDeleteProgram(s);
}

View File

@ -25,6 +25,9 @@ class GSShaderOGL {
GLuint m_pipeline; GLuint m_pipeline;
const bool m_debug_shader; const bool m_debug_shader;
std::vector<GLuint> m_prog_to_delete;
std::vector<GLuint> m_pipe_to_delete;
bool ValidateProgram(GLuint p); bool ValidateProgram(GLuint p);
bool ValidatePipeline(GLuint p); bool ValidatePipeline(GLuint p);
@ -34,11 +37,11 @@ class GSShaderOGL {
GSShaderOGL(bool debug); GSShaderOGL(bool debug);
~GSShaderOGL(); ~GSShaderOGL();
void Pipeline(GLuint vs, GLuint gs, GLuint ps); void BindPipeline(GLuint vs, GLuint gs, GLuint ps);
void BindPipeline(GLuint pipe);
GLuint Compile(const std::string& glsl_file, const std::string& entry, GLenum type, const char* glsl_h_code, const std::string& macro_sel = ""); GLuint Compile(const std::string& glsl_file, const std::string& entry, GLenum type, const char* glsl_h_code, const std::string& macro_sel = "");
GLuint LinkPipeline(GLuint vs, GLuint gs, GLuint ps);
int DumpAsm(const std::string& file, GLuint p); int DumpAsm(const std::string& file, GLuint p);
void Delete(GLuint s);
}; };

View File

@ -128,7 +128,7 @@ void GSDeviceOGL::SetupPipeline(const VSSelector& vsel, const GSSelector& gsel,
// ************************************************************* // *************************************************************
// Dynamic // Dynamic
// ************************************************************* // *************************************************************
m_shader->Pipeline(m_vs[vsel], m_gs[gsel], ps); m_shader->BindPipeline(m_vs[vsel], m_gs[gsel], ps);
} }
void GSDeviceOGL::SetupSampler(PSSamplerSelector ssel) void GSDeviceOGL::SetupSampler(PSSamplerSelector ssel)