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 gs;
GLuint vs;
GLuint pipeline;
void Clear() {
fbo = 0;
@ -89,5 +90,6 @@ namespace GLState {
ps = 0;
gs = 0;
vs = 0;
pipeline = 0;
}
}

View File

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

View File

@ -92,38 +92,27 @@ GSDeviceOGL::~GSDeviceOGL()
delete (m_va);
// 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);
// 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);
// 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_write;
delete m_convert.cb;
// Clean m_fxaa
delete m_fxaa.cb;
m_shader->Delete(m_fxaa.ps);
// Clean m_shaderfx
delete m_shaderfx.cb;
m_shader->Delete(m_shaderfx.ps);
// Clean m_date
delete m_date.dss;
// Clean shadeboost
delete m_shadeboost.cb;
m_shader->Delete(m_shadeboost.ps);
// Clean various opengl allocation
glDeleteFramebuffers(1, &m_fbo);
@ -133,11 +122,6 @@ GSDeviceOGL::~GSDeviceOGL()
delete m_vs_cb;
delete m_ps_cb;
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();
@ -744,7 +728,6 @@ void GSDeviceOGL::SelfShaderTest()
GLuint p = CompilePS(sel); \
nb_shader++; \
perf += m_shader->DumpAsm(file, p); \
m_shader->Delete(p); \
} while(0);
#define PRINT_TEST(s) \
@ -1025,7 +1008,7 @@ void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture
GSVector2i ds = dTex->GetSize();
m_shader->Pipeline(m_convert.vs, 0, ps);
m_shader->BindPipeline(m_convert.vs, 0, ps);
// ************************************
// om
@ -1263,7 +1246,7 @@ void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* ver
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

View File

@ -27,16 +27,31 @@ GSShaderOGL::GSShaderOGL(bool debug) :
m_pipeline(0),
m_debug_shader(debug)
{
glCreateProgramPipelines(1, &m_pipeline);
glBindProgramPipeline(m_pipeline);
// Create a default pipeline
m_pipeline = LinkPipeline(0, 0, 0);
BindPipeline(m_pipeline);
}
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)
{
@ -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)
{
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");
}
m_prog_to_delete.push_back(program);
return program;
}
@ -243,8 +269,3 @@ int GSShaderOGL::DumpAsm(const std::string& file, GLuint p)
return instructions;
}
void GSShaderOGL::Delete(GLuint s)
{
glDeleteProgram(s);
}

View File

@ -25,6 +25,9 @@ class GSShaderOGL {
GLuint m_pipeline;
const bool m_debug_shader;
std::vector<GLuint> m_prog_to_delete;
std::vector<GLuint> m_pipe_to_delete;
bool ValidateProgram(GLuint p);
bool ValidatePipeline(GLuint p);
@ -34,11 +37,11 @@ class GSShaderOGL {
GSShaderOGL(bool debug);
~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 LinkPipeline(GLuint vs, GLuint gs, GLuint ps);
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
// *************************************************************
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)