mirror of https://github.com/PCSX2/pcsx2.git
gsdx ogl: add code to compile a single shader
This commit is contained in:
parent
405f312fe8
commit
17988fc7de
|
@ -54,6 +54,7 @@ namespace GLState {
|
||||||
GLuint ps;
|
GLuint ps;
|
||||||
GLuint gs;
|
GLuint gs;
|
||||||
GLuint vs;
|
GLuint vs;
|
||||||
|
GLuint program;
|
||||||
GLuint pipeline;
|
GLuint pipeline;
|
||||||
|
|
||||||
void Clear() {
|
void Clear() {
|
||||||
|
@ -90,6 +91,7 @@ namespace GLState {
|
||||||
ps = 0;
|
ps = 0;
|
||||||
gs = 0;
|
gs = 0;
|
||||||
vs = 0;
|
vs = 0;
|
||||||
|
program = 0;
|
||||||
pipeline = 0;
|
pipeline = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 program;
|
||||||
extern GLuint pipeline;
|
extern GLuint pipeline;
|
||||||
|
|
||||||
extern void Clear();
|
extern void Clear();
|
||||||
|
|
|
@ -36,6 +36,10 @@ GSShaderOGL::GSShaderOGL(bool debug) :
|
||||||
|
|
||||||
GSShaderOGL::~GSShaderOGL()
|
GSShaderOGL::~GSShaderOGL()
|
||||||
{
|
{
|
||||||
|
printf("Delete %d Shaders, %d Programs, %d Pipelines\n",
|
||||||
|
m_shad_to_delete.size(), m_prog_to_delete.size(), m_pipe_to_delete.size());
|
||||||
|
|
||||||
|
for (auto s : m_shad_to_delete) glDeleteShader(s);
|
||||||
for (auto p : m_prog_to_delete) glDeleteProgram(p);
|
for (auto p : m_prog_to_delete) glDeleteProgram(p);
|
||||||
glDeleteProgramPipelines(m_pipe_to_delete.size(), &m_pipe_to_delete[0]);
|
glDeleteProgramPipelines(m_pipe_to_delete.size(), &m_pipe_to_delete[0]);
|
||||||
}
|
}
|
||||||
|
@ -53,6 +57,46 @@ GLuint GSShaderOGL::LinkPipeline(GLuint vs, GLuint gs, GLuint ps)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLuint GSShaderOGL::LinkProgram(GLuint vs, GLuint gs, GLuint ps)
|
||||||
|
{
|
||||||
|
uint32 hash = ((vs ^ gs) << 24) ^ ps;
|
||||||
|
auto it = m_program.find(hash);
|
||||||
|
if (it != m_program.end())
|
||||||
|
return it->second;
|
||||||
|
|
||||||
|
GLuint p = glCreateProgram();
|
||||||
|
if (vs) glAttachShader(p, vs);
|
||||||
|
if (ps) glAttachShader(p, ps);
|
||||||
|
if (gs) glAttachShader(p, gs);
|
||||||
|
|
||||||
|
glLinkProgram(p);
|
||||||
|
|
||||||
|
ValidateProgram(p);
|
||||||
|
|
||||||
|
m_prog_to_delete.push_back(p);
|
||||||
|
m_program[hash] = p;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GSShaderOGL::BindProgram(GLuint vs, GLuint gs, GLuint ps)
|
||||||
|
{
|
||||||
|
GLuint p = LinkProgram(vs, gs, ps);
|
||||||
|
|
||||||
|
if (GLState::program != p) {
|
||||||
|
GLState::program = p;
|
||||||
|
glUseProgram(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GSShaderOGL::BindProgram(GLuint p)
|
||||||
|
{
|
||||||
|
if (GLState::program != p) {
|
||||||
|
GLState::program = p;
|
||||||
|
glUseProgram(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GSShaderOGL::BindPipeline(GLuint vs, GLuint gs, GLuint ps)
|
void GSShaderOGL::BindPipeline(GLuint vs, GLuint gs, GLuint ps)
|
||||||
{
|
{
|
||||||
BindPipeline(m_pipeline);
|
BindPipeline(m_pipeline);
|
||||||
|
@ -85,6 +129,32 @@ void GSShaderOGL::BindPipeline(GLuint pipe)
|
||||||
GLState::pipeline = pipe;
|
GLState::pipeline = pipe;
|
||||||
glBindProgramPipeline(pipe);
|
glBindProgramPipeline(pipe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GLState::program) {
|
||||||
|
GLState::program = 0;
|
||||||
|
glUseProgram(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GSShaderOGL::ValidateShader(GLuint s)
|
||||||
|
{
|
||||||
|
if (!m_debug_shader) return true;
|
||||||
|
|
||||||
|
GLint status = 0;
|
||||||
|
glGetShaderiv(s, GL_COMPILE_STATUS, &status);
|
||||||
|
if (status) return true;
|
||||||
|
|
||||||
|
GLint log_length = 0;
|
||||||
|
glGetShaderiv(s, GL_INFO_LOG_LENGTH, &log_length);
|
||||||
|
if (log_length > 0) {
|
||||||
|
char* log = new char[log_length];
|
||||||
|
glGetShaderInfoLog(s, log_length, NULL, log);
|
||||||
|
fprintf(stderr, "%s", log);
|
||||||
|
delete[] log;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GSShaderOGL::ValidateProgram(GLuint p)
|
bool GSShaderOGL::ValidateProgram(GLuint p)
|
||||||
|
@ -208,6 +278,42 @@ GLuint GSShaderOGL::Compile(const std::string& glsl_file, const std::string& ent
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Same as above but for not-separated build
|
||||||
|
GLuint GSShaderOGL::CompileShader(const std::string& glsl_file, const std::string& entry, GLenum type, const char* glsl_h_code, const std::string& macro_sel)
|
||||||
|
{
|
||||||
|
ASSERT(glsl_h_code != NULL);
|
||||||
|
|
||||||
|
GLuint shader = 0;
|
||||||
|
|
||||||
|
// Note it is better to separate header and source file to have the good line number
|
||||||
|
// in the glsl compiler report
|
||||||
|
const int shader_nb = 3;
|
||||||
|
const char* sources[shader_nb];
|
||||||
|
|
||||||
|
std::string header = GenGlslHeader(entry, type, macro_sel);
|
||||||
|
|
||||||
|
sources[0] = header.c_str();
|
||||||
|
sources[1] = common_header_glsl;
|
||||||
|
sources[2] = glsl_h_code;
|
||||||
|
|
||||||
|
shader = glCreateShader(type);
|
||||||
|
glShaderSource(shader, shader_nb, sources, NULL);
|
||||||
|
glCompileShader(shader);
|
||||||
|
|
||||||
|
bool status = ValidateShader(shader);
|
||||||
|
|
||||||
|
if (!status) {
|
||||||
|
// print extra info
|
||||||
|
fprintf(stderr, "%s (entry %s, prog %d) :", glsl_file.c_str(), entry.c_str(), shader);
|
||||||
|
fprintf(stderr, "\n%s", macro_sel.c_str());
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shad_to_delete.push_back(shader);
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
// This function will get the binary program. Normally it must be used a caching
|
// This function will get the binary program. Normally it must be used a caching
|
||||||
// solution but Nvidia also incorporates the ASM dump. Asm is nice because it allow
|
// solution but Nvidia also incorporates the ASM dump. Asm is nice because it allow
|
||||||
// to have an overview of the program performance based on the instruction number
|
// to have an overview of the program performance based on the instruction number
|
||||||
|
|
|
@ -23,11 +23,14 @@
|
||||||
|
|
||||||
class GSShaderOGL {
|
class GSShaderOGL {
|
||||||
GLuint m_pipeline;
|
GLuint m_pipeline;
|
||||||
|
hash_map<uint32, GLuint> m_program;
|
||||||
const bool m_debug_shader;
|
const bool m_debug_shader;
|
||||||
|
|
||||||
|
std::vector<GLuint> m_shad_to_delete;
|
||||||
std::vector<GLuint> m_prog_to_delete;
|
std::vector<GLuint> m_prog_to_delete;
|
||||||
std::vector<GLuint> m_pipe_to_delete;
|
std::vector<GLuint> m_pipe_to_delete;
|
||||||
|
|
||||||
|
bool ValidateShader(GLuint s);
|
||||||
bool ValidateProgram(GLuint p);
|
bool ValidateProgram(GLuint p);
|
||||||
bool ValidatePipeline(GLuint p);
|
bool ValidatePipeline(GLuint p);
|
||||||
|
|
||||||
|
@ -43,5 +46,12 @@ class GSShaderOGL {
|
||||||
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);
|
GLuint LinkPipeline(GLuint vs, GLuint gs, GLuint ps);
|
||||||
|
|
||||||
|
// Same as above but for not separated build
|
||||||
|
void BindProgram(GLuint vs, GLuint gs, GLuint ps);
|
||||||
|
void BindProgram(GLuint p);
|
||||||
|
|
||||||
|
GLuint CompileShader(const std::string& glsl_file, const std::string& entry, GLenum type, const char* glsl_h_code, const std::string& macro_sel = "");
|
||||||
|
GLuint LinkProgram(GLuint vs, GLuint gs, GLuint ps);
|
||||||
|
|
||||||
int DumpAsm(const std::string& file, GLuint p);
|
int DumpAsm(const std::string& file, GLuint p);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue