mirror of https://github.com/PCSX2/pcsx2.git
gsdx: split shader/program/pipeline object management into a separate class
* remove the possibility to compile shader from file. Some people loads older shaders... The feature might be readded later git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5697 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
544c84a344
commit
dc036ff59d
|
@ -89,6 +89,7 @@ set(GSdxSources
|
|||
GSSetupPrimCodeGenerator.x64.avx.cpp
|
||||
GSSetupPrimCodeGenerator.x86.cpp
|
||||
GSSetupPrimCodeGenerator.x64.cpp
|
||||
GSShaderOGL.cpp
|
||||
GSState.cpp
|
||||
GSTables.cpp
|
||||
GSTexture.cpp
|
||||
|
|
|
@ -30,7 +30,6 @@ PFNGLBINDBUFFERPROC gl_BindBuffer = NULL;
|
|||
PFNGLBINDBUFFERBASEPROC gl_BindBufferBase = NULL;
|
||||
PFNGLBINDFRAGDATALOCATIONINDEXEDPROC gl_BindFragDataLocationIndexed = NULL;
|
||||
PFNGLBINDFRAMEBUFFERPROC gl_BindFramebuffer = NULL;
|
||||
PFNGLBINDPROGRAMPIPELINEPROC gl_BindProgramPipeline = NULL;
|
||||
PFNGLBINDSAMPLERPROC gl_BindSampler = NULL;
|
||||
PFNGLBINDVERTEXARRAYPROC gl_BindVertexArray = NULL;
|
||||
PFNGLBLENDEQUATIONSEPARATEPROC gl_BlendEquationSeparate = NULL;
|
||||
|
@ -48,7 +47,6 @@ PFNGLCREATESHADERPROGRAMVPROC gl_CreateShaderProgramv = NULL;
|
|||
PFNGLDELETEBUFFERSPROC gl_DeleteBuffers = NULL;
|
||||
PFNGLDELETEFRAMEBUFFERSPROC gl_DeleteFramebuffers = NULL;
|
||||
PFNGLDELETEPROGRAMPROC gl_DeleteProgram = NULL;
|
||||
PFNGLDELETEPROGRAMPIPELINESPROC gl_DeleteProgramPipelines = NULL;
|
||||
PFNGLDELETESAMPLERSPROC gl_DeleteSamplers = NULL;
|
||||
PFNGLDELETESHADERPROC gl_DeleteShader = NULL;
|
||||
PFNGLDELETEVERTEXARRAYSPROC gl_DeleteVertexArrays = NULL;
|
||||
|
@ -60,7 +58,6 @@ PFNGLFRAMEBUFFERRENDERBUFFERPROC gl_FramebufferRenderbuffer = NULL;
|
|||
PFNGLFRAMEBUFFERTEXTURE2DPROC gl_FramebufferTexture2D = NULL;
|
||||
PFNGLGENBUFFERSPROC gl_GenBuffers = NULL;
|
||||
PFNGLGENFRAMEBUFFERSPROC gl_GenFramebuffers = NULL;
|
||||
PFNGLGENPROGRAMPIPELINESPROC gl_GenProgramPipelines = NULL;
|
||||
PFNGLGENSAMPLERSPROC gl_GenSamplers = NULL;
|
||||
PFNGLGENVERTEXARRAYSPROC gl_GenVertexArrays = NULL;
|
||||
PFNGLGETBUFFERPARAMETERIVPROC gl_GetBufferParameteriv = NULL;
|
||||
|
@ -86,6 +83,13 @@ PFNGLVERTEXATTRIBIPOINTERPROC gl_VertexAttribIPointer = NULL;
|
|||
PFNGLVERTEXATTRIBPOINTERPROC gl_VertexAttribPointer = NULL;
|
||||
PFNGLTEXSTORAGE2DPROC gl_TexStorage2D = NULL;
|
||||
PFNGLBUFFERSUBDATAPROC gl_BufferSubData = NULL;
|
||||
// GL 4.1
|
||||
PFNGLBINDPROGRAMPIPELINEPROC gl_BindProgramPipeline = NULL;
|
||||
PFNGLGENPROGRAMPIPELINESPROC gl_GenProgramPipelines = NULL;
|
||||
PFNGLDELETEPROGRAMPIPELINESPROC gl_DeleteProgramPipelines = NULL;
|
||||
PFNGLGETPROGRAMPIPELINEIVPROC gl_GetProgramPipelineiv = NULL;
|
||||
PFNGLVALIDATEPROGRAMPIPELINEPROC gl_ValidateProgramPipeline = NULL;
|
||||
PFNGLGETPROGRAMPIPELINEINFOLOGPROC gl_GetProgramPipelineInfoLog = NULL;
|
||||
// NO GL4.1
|
||||
PFNGLUSEPROGRAMPROC gl_UseProgram = NULL;
|
||||
PFNGLGETSHADERINFOLOGPROC gl_GetShaderInfoLog = NULL;
|
||||
|
|
|
@ -28,7 +28,6 @@ extern PFNGLBINDBUFFERPROC gl_BindBuffer;
|
|||
extern PFNGLBINDBUFFERBASEPROC gl_BindBufferBase;
|
||||
extern PFNGLBINDFRAGDATALOCATIONINDEXEDPROC gl_BindFragDataLocationIndexed;
|
||||
extern PFNGLBINDFRAMEBUFFERPROC gl_BindFramebuffer;
|
||||
extern PFNGLBINDPROGRAMPIPELINEPROC gl_BindProgramPipeline;
|
||||
extern PFNGLBINDSAMPLERPROC gl_BindSampler;
|
||||
extern PFNGLBINDVERTEXARRAYPROC gl_BindVertexArray;
|
||||
extern PFNGLBLENDEQUATIONSEPARATEPROC gl_BlendEquationSeparate;
|
||||
|
@ -46,7 +45,6 @@ extern PFNGLCREATESHADERPROGRAMVPROC gl_CreateShaderProgramv;
|
|||
extern PFNGLDELETEBUFFERSPROC gl_DeleteBuffers;
|
||||
extern PFNGLDELETEFRAMEBUFFERSPROC gl_DeleteFramebuffers;
|
||||
extern PFNGLDELETEPROGRAMPROC gl_DeleteProgram;
|
||||
extern PFNGLDELETEPROGRAMPIPELINESPROC gl_DeleteProgramPipelines;
|
||||
extern PFNGLDELETESAMPLERSPROC gl_DeleteSamplers;
|
||||
extern PFNGLDELETESHADERPROC gl_DeleteShader;
|
||||
extern PFNGLDELETEVERTEXARRAYSPROC gl_DeleteVertexArrays;
|
||||
|
@ -58,7 +56,6 @@ extern PFNGLFRAMEBUFFERRENDERBUFFERPROC gl_FramebufferRenderbuffer;
|
|||
extern PFNGLFRAMEBUFFERTEXTURE2DPROC gl_FramebufferTexture2D;
|
||||
extern PFNGLGENBUFFERSPROC gl_GenBuffers;
|
||||
extern PFNGLGENFRAMEBUFFERSPROC gl_GenFramebuffers;
|
||||
extern PFNGLGENPROGRAMPIPELINESPROC gl_GenProgramPipelines;
|
||||
extern PFNGLGENSAMPLERSPROC gl_GenSamplers;
|
||||
extern PFNGLGENVERTEXARRAYSPROC gl_GenVertexArrays;
|
||||
extern PFNGLGETBUFFERPARAMETERIVPROC gl_GetBufferParameteriv;
|
||||
|
@ -84,6 +81,13 @@ extern PFNGLVERTEXATTRIBIPOINTERPROC gl_VertexAttribIPointer;
|
|||
extern PFNGLVERTEXATTRIBPOINTERPROC gl_VertexAttribPointer;
|
||||
extern PFNGLTEXSTORAGE2DPROC gl_TexStorage2D;
|
||||
extern PFNGLBUFFERSUBDATAPROC gl_BufferSubData;
|
||||
// GL4.1
|
||||
extern PFNGLBINDPROGRAMPIPELINEPROC gl_BindProgramPipeline;
|
||||
extern PFNGLDELETEPROGRAMPIPELINESPROC gl_DeleteProgramPipelines;
|
||||
extern PFNGLGENPROGRAMPIPELINESPROC gl_GenProgramPipelines;
|
||||
extern PFNGLGETPROGRAMPIPELINEIVPROC gl_GetProgramPipelineiv;
|
||||
extern PFNGLVALIDATEPROGRAMPIPELINEPROC gl_ValidateProgramPipeline;
|
||||
extern PFNGLGETPROGRAMPIPELINEINFOLOGPROC gl_GetProgramPipelineInfoLog;
|
||||
// NO GL4.1
|
||||
extern PFNGLUSEPROGRAMPROC gl_UseProgram;
|
||||
extern PFNGLGETSHADERINFOLOGPROC gl_GetShaderInfoLog;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2011 Gregory hainaut
|
||||
* Copyright (C) 2011-2013 Gregory hainaut
|
||||
* Copyright (C) 2007-2009 Gabest
|
||||
*
|
||||
* This Program is free software; you can redistribute it and/or modify
|
||||
|
@ -56,9 +56,9 @@ GSDeviceOGL::GSDeviceOGL()
|
|||
, m_fbo(0)
|
||||
, m_fbo_read(0)
|
||||
, m_vb_sr(NULL)
|
||||
, m_shader(NULL)
|
||||
{
|
||||
m_msaa = !!theApp.GetConfig("UserHacks", 0) ? theApp.GetConfig("UserHacks_MSAA", 0) : 0;
|
||||
m_debug_shader = !!theApp.GetConfig("debug_ogl_shader", 1);
|
||||
|
||||
memset(&m_merge_obj, 0, sizeof(m_merge_obj));
|
||||
memset(&m_interlace, 0, sizeof(m_interlace));
|
||||
|
@ -75,36 +75,28 @@ GSDeviceOGL::GSDeviceOGL()
|
|||
|
||||
GSDeviceOGL::~GSDeviceOGL()
|
||||
{
|
||||
// If the create function wasn't called nothing to do.
|
||||
if (m_shader == NULL)
|
||||
return;
|
||||
|
||||
// Clean vertex buffer state
|
||||
delete (m_vb_sr);
|
||||
|
||||
// Clean m_merge_obj
|
||||
for (uint32 i = 0; i < 2; i++)
|
||||
if (GLLoader::found_GL_ARB_separate_shader_objects)
|
||||
gl_DeleteProgram(m_merge_obj.ps[i]);
|
||||
else
|
||||
gl_DeleteShader(m_merge_obj.ps[i]);
|
||||
m_shader->Delete(m_merge_obj.ps[i]);
|
||||
delete (m_merge_obj.cb);
|
||||
delete (m_merge_obj.bs);
|
||||
|
||||
|
||||
// Clean m_interlace
|
||||
for (uint32 i = 0; i < 2; i++)
|
||||
if (GLLoader::found_GL_ARB_separate_shader_objects)
|
||||
gl_DeleteProgram(m_interlace.ps[i]);
|
||||
else
|
||||
gl_DeleteShader(m_interlace.ps[i]);
|
||||
m_shader->Delete(m_interlace.ps[i]);
|
||||
delete (m_interlace.cb);
|
||||
|
||||
// Clean m_convert
|
||||
if (GLLoader::found_GL_ARB_separate_shader_objects) {
|
||||
gl_DeleteProgram(m_convert.vs);
|
||||
for (uint32 i = 0; i < 2; i++)
|
||||
gl_DeleteProgram(m_convert.ps[i]);
|
||||
} else {
|
||||
gl_DeleteShader(m_convert.vs);
|
||||
for (uint32 i = 0; i < 2; i++)
|
||||
gl_DeleteShader(m_convert.ps[i]);
|
||||
}
|
||||
m_shader->Delete(m_convert.vs);
|
||||
for (uint32 i = 0; i < 2; i++)
|
||||
m_shader->Delete(m_convert.ps[i]);
|
||||
gl_DeleteSamplers(1, &m_convert.ln);
|
||||
gl_DeleteSamplers(1, &m_convert.pt);
|
||||
delete m_convert.dss;
|
||||
|
@ -112,11 +104,7 @@ GSDeviceOGL::~GSDeviceOGL()
|
|||
|
||||
// Clean m_fxaa
|
||||
delete m_fxaa.cb;
|
||||
if (GLLoader::found_GL_ARB_separate_shader_objects) {
|
||||
gl_DeleteProgram(m_fxaa.ps);
|
||||
} else {
|
||||
gl_DeleteShader(m_fxaa.ps);
|
||||
}
|
||||
m_shader->Delete(m_fxaa.ps);
|
||||
|
||||
// Clean m_date
|
||||
delete m_date.dss;
|
||||
|
@ -124,16 +112,10 @@ GSDeviceOGL::~GSDeviceOGL()
|
|||
|
||||
// Clean shadeboost
|
||||
delete m_shadeboost.cb;
|
||||
if (GLLoader::found_GL_ARB_separate_shader_objects) {
|
||||
gl_DeleteProgram(m_shadeboost.ps);
|
||||
} else {
|
||||
gl_DeleteShader(m_shadeboost.ps);
|
||||
}
|
||||
m_shader->Delete(m_shadeboost.ps);
|
||||
|
||||
|
||||
// Clean various opengl allocation
|
||||
if (GLLoader::found_GL_ARB_separate_shader_objects)
|
||||
gl_DeleteProgramPipelines(1, &m_pipeline);
|
||||
gl_DeleteFramebuffers(1, &m_fbo);
|
||||
gl_DeleteFramebuffers(1, &m_fbo_read);
|
||||
|
||||
|
@ -143,19 +125,10 @@ GSDeviceOGL::~GSDeviceOGL()
|
|||
gl_DeleteSamplers(1, &m_palette_ss);
|
||||
delete m_vb;
|
||||
|
||||
for (uint32 key = 0; key < VSSelector::size(); key++) m_shader->Delete(m_vs[key]);
|
||||
for (uint32 key = 0; key < GSSelector::size(); key++) m_shader->Delete(m_gs[key]);
|
||||
for (auto it = m_ps.begin(); it != m_ps.end() ; it++) m_shader->Delete(it->second);
|
||||
|
||||
if (GLLoader::found_GL_ARB_separate_shader_objects) {
|
||||
for (uint32 key = 0; key < VSSelector::size(); key++) gl_DeleteProgram(m_vs[key]);
|
||||
for (uint32 key = 0; key < GSSelector::size(); key++) gl_DeleteProgram(m_gs[key]);
|
||||
for (auto it = m_ps.begin(); it != m_ps.end() ; it++) gl_DeleteProgram(it->second);
|
||||
} else {
|
||||
for (uint32 key = 0; key < VSSelector::size(); key++) gl_DeleteShader(m_vs[key]);
|
||||
for (uint32 key = 0; key < GSSelector::size(); key++) gl_DeleteShader(m_gs[key]);
|
||||
for (auto it = m_ps.begin(); it != m_ps.end() ; it++) gl_DeleteShader(it->second);
|
||||
|
||||
for (auto it = m_single_prog.begin(); it != m_single_prog.end() ; it++) gl_DeleteProgram(it->second);
|
||||
m_single_prog.clear();
|
||||
}
|
||||
m_ps.clear();
|
||||
|
||||
gl_DeleteSamplers(PSSamplerSelector::size(), m_ps_ss);
|
||||
|
@ -215,10 +188,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
|||
// ****************************************************************
|
||||
// Various object
|
||||
// ****************************************************************
|
||||
if (GLLoader::found_GL_ARB_separate_shader_objects) {
|
||||
gl_GenProgramPipelines(1, &m_pipeline);
|
||||
gl_BindProgramPipeline(m_pipeline);
|
||||
}
|
||||
m_shader = new GSShaderOGL(!!theApp.GetConfig("debug_ogl_shader", 1), GLLoader::found_GL_ARB_separate_shader_objects, GLLoader::found_GL_ARB_shading_language_420pack);
|
||||
|
||||
gl_GenFramebuffers(1, &m_fbo);
|
||||
gl_GenFramebuffers(1, &m_fbo_read);
|
||||
|
@ -236,29 +206,14 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
|||
// ****************************************************************
|
||||
// convert
|
||||
// ****************************************************************
|
||||
CompileShaderFromSource("convert.glsl", "vs_main", GL_VERTEX_SHADER, &m_convert.vs, convert_glsl);
|
||||
m_convert.vs = m_shader->Compile("convert.glsl", "vs_main", GL_VERTEX_SHADER, convert_glsl);
|
||||
for(size_t i = 0; i < countof(m_convert.ps); i++)
|
||||
CompileShaderFromSource("convert.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &m_convert.ps[i], convert_glsl);
|
||||
m_convert.ps[i] = m_shader->Compile("convert.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, convert_glsl);
|
||||
|
||||
// Note the following object are initialized to 0 so disabled.
|
||||
// Note: maybe enable blend with a factor of 1
|
||||
// m_convert.dss, m_convert.bs
|
||||
|
||||
#if 0
|
||||
memset(&dsd, 0, sizeof(dsd));
|
||||
|
||||
dsd.DepthEnable = false;
|
||||
dsd.StencilEnable = false;
|
||||
|
||||
hr = m_dev->CreateDepthStencilState(&dsd, &m_convert.dss);
|
||||
|
||||
memset(&bsd, 0, sizeof(bsd));
|
||||
|
||||
bsd.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
||||
|
||||
hr = m_dev->CreateBlendState(&bsd, &m_convert.bs);
|
||||
#endif
|
||||
|
||||
m_convert.ln = CreateSampler(true, false, false);
|
||||
m_convert.pt = CreateSampler(false, false, false);
|
||||
|
||||
|
@ -271,7 +226,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
|||
m_merge_obj.cb = new GSUniformBufferOGL(g_merge_cb_index, sizeof(MergeConstantBuffer));
|
||||
|
||||
for(size_t i = 0; i < countof(m_merge_obj.ps); i++)
|
||||
CompileShaderFromSource("merge.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &m_merge_obj.ps[i], merge_glsl);
|
||||
m_merge_obj.ps[i] = m_shader->Compile("merge.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, merge_glsl);
|
||||
|
||||
m_merge_obj.bs = new GSBlendStateOGL();
|
||||
m_merge_obj.bs->EnableBlend();
|
||||
|
@ -283,7 +238,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
|||
m_interlace.cb = new GSUniformBufferOGL(g_interlace_cb_index, sizeof(InterlaceConstantBuffer));
|
||||
|
||||
for(size_t i = 0; i < countof(m_interlace.ps); i++)
|
||||
CompileShaderFromSource("interlace.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &m_interlace.ps[i], interlace_glsl);
|
||||
m_interlace.ps[i] = m_shader->Compile("interlace.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, interlace_glsl);
|
||||
// ****************************************************************
|
||||
// Shade boost
|
||||
// ****************************************************************
|
||||
|
@ -296,7 +251,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
|||
+ format("#define SB_BRIGHTNESS %d\n", ShadeBoost_Brightness)
|
||||
+ format("#define SB_CONTRAST %d\n", ShadeBoost_Contrast);
|
||||
|
||||
CompileShaderFromSource("shadeboost.glsl", "ps_main", GL_FRAGMENT_SHADER, &m_shadeboost.ps, shadeboost_glsl, shade_macro);
|
||||
m_shadeboost.ps = m_shader->Compile("shadeboost.glsl", "ps_main", GL_FRAGMENT_SHADER, shadeboost_glsl, shade_macro);
|
||||
|
||||
// ****************************************************************
|
||||
// rasterization configuration
|
||||
|
@ -321,13 +276,9 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
|||
rd.AntialiasedLineEnable = false;
|
||||
#endif
|
||||
|
||||
// TODO Later
|
||||
// ****************************************************************
|
||||
// fxaa (bonus)
|
||||
// ****************************************************************
|
||||
// FIXME need to define FXAA_GLSL_130 for the shader
|
||||
// FIXME need to manually set the index...
|
||||
// FIXME need dofxaa interface too
|
||||
std::string fxaa_macro = "#define FXAA_GLSL_130 1\n";
|
||||
if (GLLoader::found_GL_ARB_gpu_shader5) {
|
||||
// This extension become core on openGL4
|
||||
|
@ -335,7 +286,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
|||
fxaa_macro += "#define FXAA_GATHER4_ALPHA 1\n";
|
||||
}
|
||||
m_fxaa.cb = new GSUniformBufferOGL(g_fxaa_cb_index, sizeof(FXAAConstantBuffer));
|
||||
CompileShaderFromSource("fxaa.fx", "ps_main", GL_FRAGMENT_SHADER, &m_fxaa.ps, fxaa_fx, fxaa_macro);
|
||||
m_fxaa.ps = m_shader->Compile("fxaa.fx", "ps_main", GL_FRAGMENT_SHADER, fxaa_fx, fxaa_macro);
|
||||
|
||||
// ****************************************************************
|
||||
// DATE
|
||||
|
@ -457,102 +408,10 @@ void GSDeviceOGL::Flip()
|
|||
#endif
|
||||
}
|
||||
|
||||
static void set_uniform_buffer_binding(GLuint prog, GLchar* name, GLuint binding) {
|
||||
GLuint index;
|
||||
index = gl_GetUniformBlockIndex(prog, name);
|
||||
if (index != GL_INVALID_INDEX) {
|
||||
gl_UniformBlockBinding(prog, index, binding);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_sampler_uniform_binding(GLuint prog, GLchar* name, GLuint binding) {
|
||||
GLint loc = gl_GetUniformLocation(prog, name);
|
||||
if (loc != -1) {
|
||||
if (GLLoader::found_GL_ARB_separate_shader_objects) {
|
||||
gl_ProgramUniform1i(prog, loc, binding);
|
||||
} else {
|
||||
gl_Uniform1i(loc, binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GLuint GSDeviceOGL::link_prog()
|
||||
{
|
||||
GLuint single_prog = gl_CreateProgram();
|
||||
if (m_state.vs) gl_AttachShader(single_prog, m_state.vs);
|
||||
if (m_state.ps) gl_AttachShader(single_prog, m_state.ps);
|
||||
if (m_state.gs) gl_AttachShader(single_prog, m_state.gs);
|
||||
|
||||
gl_LinkProgram(single_prog);
|
||||
|
||||
GLint status;
|
||||
gl_GetProgramiv(single_prog, GL_LINK_STATUS, &status);
|
||||
if (!status) {
|
||||
GLint log_length = 0;
|
||||
gl_GetProgramiv(single_prog, GL_INFO_LOG_LENGTH, &log_length);
|
||||
if (log_length > 0) {
|
||||
char* log = new char[log_length];
|
||||
gl_GetProgramInfoLog(single_prog, log_length, NULL, log);
|
||||
fprintf(stderr, "%s", log);
|
||||
delete[] log;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (m_state.vs) gl_DetachShader(single_prog, m_state.vs);
|
||||
if (m_state.ps) gl_DetachShader(single_prog, m_state.ps);
|
||||
if (m_state.gs) gl_DetachShader(single_prog, m_state.gs);
|
||||
#endif
|
||||
|
||||
return single_prog;
|
||||
}
|
||||
|
||||
void GSDeviceOGL::BeforeDraw()
|
||||
{
|
||||
hash_map<uint64, GLuint >::iterator single_prog;
|
||||
|
||||
|
||||
if (!GLLoader::found_GL_ARB_separate_shader_objects) {
|
||||
// Note: shader are integer lookup pointer. They start from 1 and incr
|
||||
// every time you create a new shader OR a new program.
|
||||
uint64 sel = (uint64)m_state.vs << 40 | (uint64)m_state.gs << 20 | m_state.ps;
|
||||
single_prog = m_single_prog.find(sel);
|
||||
if (single_prog == m_single_prog.end()) {
|
||||
m_single_prog[sel] = link_prog();
|
||||
single_prog = m_single_prog.find(sel);
|
||||
}
|
||||
|
||||
gl_UseProgram(single_prog->second);
|
||||
}
|
||||
|
||||
if (!GLLoader::found_GL_ARB_shading_language_420pack) {
|
||||
if (GLLoader::found_GL_ARB_separate_shader_objects) {
|
||||
set_uniform_buffer_binding(m_state.vs, "cb20", 20);
|
||||
set_uniform_buffer_binding(m_state.ps, "cb21", 21);
|
||||
|
||||
set_uniform_buffer_binding(m_state.ps, "cb10", 10);
|
||||
set_uniform_buffer_binding(m_state.ps, "cb11", 11);
|
||||
set_uniform_buffer_binding(m_state.ps, "cb12", 12);
|
||||
set_uniform_buffer_binding(m_state.ps, "cb13", 13);
|
||||
|
||||
set_sampler_uniform_binding(m_state.ps, "TextureSampler", 0);
|
||||
set_sampler_uniform_binding(m_state.ps, "PaletteSampler", 1);
|
||||
set_sampler_uniform_binding(m_state.ps, "RTCopySampler", 2);
|
||||
} else {
|
||||
set_uniform_buffer_binding(single_prog->second, "cb20", 20);
|
||||
set_uniform_buffer_binding(single_prog->second, "cb21", 21);
|
||||
|
||||
set_uniform_buffer_binding(single_prog->second, "cb10", 10);
|
||||
set_uniform_buffer_binding(single_prog->second, "cb11", 11);
|
||||
set_uniform_buffer_binding(single_prog->second, "cb12", 12);
|
||||
set_uniform_buffer_binding(single_prog->second, "cb13", 13);
|
||||
|
||||
set_sampler_uniform_binding(single_prog->second, "TextureSampler", 0);
|
||||
set_sampler_uniform_binding(single_prog->second, "PaletteSampler", 1);
|
||||
set_sampler_uniform_binding(single_prog->second, "RTCopySampler", 2);
|
||||
}
|
||||
}
|
||||
m_shader->UseProgram();
|
||||
m_shader->SetupUniform();
|
||||
}
|
||||
|
||||
void GSDeviceOGL::AfterDraw()
|
||||
|
@ -875,13 +734,13 @@ void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt,
|
|||
// vs
|
||||
// ************************************
|
||||
|
||||
VSSetShader(m_convert.vs);
|
||||
m_shader->VS(m_convert.vs);
|
||||
|
||||
// ************************************
|
||||
// gs
|
||||
// ************************************
|
||||
|
||||
GSSetShader(0);
|
||||
m_shader->GS(0);
|
||||
|
||||
// ************************************
|
||||
// ps
|
||||
|
@ -889,7 +748,7 @@ void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt,
|
|||
|
||||
PSSetShaderResources(st, NULL);
|
||||
PSSetSamplerState(linear ? m_convert.ln : m_convert.pt, 0);
|
||||
PSSetShader(ps);
|
||||
m_shader->PS(ps);
|
||||
|
||||
// ************************************
|
||||
// Draw
|
||||
|
@ -1006,11 +865,11 @@ void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* ver
|
|||
|
||||
// vs
|
||||
|
||||
VSSetShader(m_convert.vs);
|
||||
m_shader->VS(m_convert.vs);
|
||||
|
||||
// gs
|
||||
|
||||
GSSetShader(0);
|
||||
m_shader->GS(0);
|
||||
|
||||
// ps
|
||||
|
||||
|
@ -1018,7 +877,7 @@ void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* ver
|
|||
|
||||
PSSetShaderResources(rt2, NULL);
|
||||
PSSetSamplerState(m_convert.pt, 0);
|
||||
PSSetShader(m_convert.ps[datm ? 2 : 3]);
|
||||
m_shader->PS(m_convert.ps[datm ? 2 : 3]);
|
||||
|
||||
//
|
||||
|
||||
|
@ -1104,26 +963,6 @@ void GSDeviceOGL::IASetPrimitiveTopology(GLenum topology)
|
|||
m_state.vb->SetTopology(topology);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::VSSetShader(GLuint vs)
|
||||
{
|
||||
if (m_state.vs != vs)
|
||||
{
|
||||
m_state.vs = vs;
|
||||
if (GLLoader::found_GL_ARB_separate_shader_objects)
|
||||
gl_UseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, vs);
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceOGL::GSSetShader(GLuint gs)
|
||||
{
|
||||
if (m_state.gs != gs)
|
||||
{
|
||||
m_state.gs = gs;
|
||||
if (GLLoader::found_GL_ARB_separate_shader_objects)
|
||||
gl_UseProgramStages(m_pipeline, GL_GEOMETRY_SHADER_BIT, gs);
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceOGL::PSSetShaderResources(GSTexture* sr0, GSTexture* sr1)
|
||||
{
|
||||
PSSetShaderResource(0, sr0);
|
||||
|
@ -1155,16 +994,6 @@ void GSDeviceOGL::PSSetSamplerState(GLuint ss0, GLuint ss1, GLuint ss2)
|
|||
}
|
||||
}
|
||||
|
||||
void GSDeviceOGL::PSSetShader(GLuint ps)
|
||||
{
|
||||
if (m_state.ps != ps)
|
||||
{
|
||||
m_state.ps = ps;
|
||||
if (GLLoader::found_GL_ARB_separate_shader_objects)
|
||||
gl_UseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, ps);
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceOGL::OMSetFBO(GLuint fbo, GLenum buffer)
|
||||
{
|
||||
if (m_state.fbo != fbo) {
|
||||
|
@ -1247,161 +1076,6 @@ void GSDeviceOGL::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVecto
|
|||
}
|
||||
}
|
||||
|
||||
void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const std::string& entry, GLenum type, GLuint* program, const char* glsl_h_code, const std::string& macro_sel)
|
||||
{
|
||||
// Not supported
|
||||
if (type == GL_GEOMETRY_SHADER && !GLLoader::found_geometry_shader) {
|
||||
*program = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// *****************************************************
|
||||
// Build a header string
|
||||
// *****************************************************
|
||||
// First select the version (must be the first line so we need to generate it
|
||||
std::string version;
|
||||
if (GLLoader::found_only_gl30) {
|
||||
version = "#version 130\n";
|
||||
} else {
|
||||
version = "#version 330\n";
|
||||
}
|
||||
if (GLLoader::found_GL_ARB_shading_language_420pack) {
|
||||
version += "#extension GL_ARB_shading_language_420pack: require\n";
|
||||
} else {
|
||||
version += "#define DISABLE_GL42\n";
|
||||
}
|
||||
if (GLLoader::found_GL_ARB_separate_shader_objects) {
|
||||
version += "#extension GL_ARB_separate_shader_objects : require\n";
|
||||
} else {
|
||||
if (!GLLoader::fglrx_buggy_driver)
|
||||
version += "#define DISABLE_SSO\n";
|
||||
}
|
||||
if (GLLoader::found_only_gl30) {
|
||||
version += "#extension GL_ARB_explicit_attrib_location : require\n";
|
||||
version += "#extension GL_ARB_uniform_buffer_object : require\n";
|
||||
}
|
||||
#ifdef ENABLE_OGL_STENCIL_DEBUG
|
||||
version += "#define ENABLE_OGL_STENCIL_DEBUG 1\n";
|
||||
#endif
|
||||
|
||||
// Allow to puts several shader in 1 files
|
||||
std::string shader_type;
|
||||
switch (type) {
|
||||
case GL_VERTEX_SHADER:
|
||||
shader_type = "#define VERTEX_SHADER 1\n";
|
||||
break;
|
||||
case GL_GEOMETRY_SHADER:
|
||||
shader_type = "#define GEOMETRY_SHADER 1\n";
|
||||
break;
|
||||
case GL_FRAGMENT_SHADER:
|
||||
shader_type = "#define FRAGMENT_SHADER 1\n";
|
||||
break;
|
||||
default: ASSERT(0);
|
||||
}
|
||||
|
||||
// Select the entry point ie the main function
|
||||
std::string entry_main = format("#define %s main\n", entry.c_str());
|
||||
|
||||
std::string header = version + shader_type + entry_main + macro_sel;
|
||||
|
||||
// *****************************************************
|
||||
// Read the source file
|
||||
// *****************************************************
|
||||
std::string source;
|
||||
std::string line;
|
||||
// Each linux distributions have his rules for path so we give them the possibility to
|
||||
// change it with compilation flags. -- Gregory
|
||||
#ifdef GLSL_SHADER_DIR_COMPILATION
|
||||
#define xGLSL_SHADER_DIR_str(s) GLSL_SHADER_DIR_str(s)
|
||||
#define GLSL_SHADER_DIR_str(s) #s
|
||||
const std::string shader_file = string(xGLSL_SHADER_DIR_str(GLSL_SHADER_DIR_COMPILATION)) + '/' + glsl_file;
|
||||
#else
|
||||
const std::string shader_file = string("plugins/") + glsl_file;
|
||||
#endif
|
||||
std::ifstream myfile(shader_file.c_str());
|
||||
bool failed_to_open_glsl = true;
|
||||
if (myfile.is_open()) {
|
||||
while ( myfile.good() )
|
||||
{
|
||||
getline (myfile,line);
|
||||
source += line;
|
||||
source += '\n';
|
||||
}
|
||||
myfile.close();
|
||||
failed_to_open_glsl = false;
|
||||
}
|
||||
|
||||
|
||||
// Note it is better to separate header and source file to have the good line number
|
||||
// in the glsl compiler report
|
||||
const char** sources_array = (const char**)malloc(2*sizeof(char*));
|
||||
|
||||
char* header_str = (char*)malloc(header.size() + 1);
|
||||
sources_array[0] = header_str;
|
||||
header.copy(header_str, header.size(), 0);
|
||||
header_str[header.size()] = '\0';
|
||||
|
||||
char* source_str = (char*)malloc(source.size() + 1);
|
||||
if (failed_to_open_glsl) {
|
||||
if (glsl_h_code)
|
||||
sources_array[1] = glsl_h_code;
|
||||
else
|
||||
sources_array[1] = '\0';
|
||||
} else {
|
||||
sources_array[1] = source_str;
|
||||
source.copy(source_str, source.size(), 0);
|
||||
source_str[source.size()] = '\0';
|
||||
}
|
||||
|
||||
|
||||
if (GLLoader::found_GL_ARB_separate_shader_objects) {
|
||||
#if 0
|
||||
// Could be useful one day
|
||||
const GLchar* ShaderSource[1];
|
||||
ShaderSource[0] = header.append(source).c_str();
|
||||
*program = gl_CreateShaderProgramv(type, 1, &ShaderSource[0]);
|
||||
#else
|
||||
*program = gl_CreateShaderProgramv(type, 2, sources_array);
|
||||
#endif
|
||||
} else {
|
||||
*program = gl_CreateShader(type);
|
||||
gl_ShaderSource(*program, 2, sources_array, NULL);
|
||||
gl_CompileShader(*program);
|
||||
}
|
||||
|
||||
free(source_str);
|
||||
free(header_str);
|
||||
free(sources_array);
|
||||
|
||||
if (m_debug_shader) {
|
||||
GLint log_length = 0;
|
||||
GLint status = false;
|
||||
if (GLLoader::found_GL_ARB_separate_shader_objects) {
|
||||
gl_GetProgramiv(*program, GL_INFO_LOG_LENGTH, &log_length);
|
||||
gl_GetProgramiv(*program, GL_LINK_STATUS, &status);
|
||||
} else {
|
||||
gl_GetShaderiv(*program, GL_INFO_LOG_LENGTH, &log_length);
|
||||
gl_GetShaderiv(*program, GL_COMPILE_STATUS, &status);
|
||||
}
|
||||
|
||||
if (log_length > 0 && !status) {
|
||||
// Print a nice debug log
|
||||
fprintf(stderr, "%s (entry %s, prog %d) :", glsl_file.c_str(), entry.c_str(), *program);
|
||||
fprintf(stderr, "\n%s", macro_sel.c_str());
|
||||
|
||||
char* log = new char[log_length];
|
||||
if (GLLoader::found_GL_ARB_separate_shader_objects)
|
||||
gl_GetProgramInfoLog(*program, log_length, NULL, log);
|
||||
else
|
||||
gl_GetShaderInfoLog(*program, log_length, NULL, log);
|
||||
|
||||
fprintf(stderr, "%s", log);
|
||||
fprintf(stderr, "\n");
|
||||
delete[] log;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceOGL::CheckDebugLog()
|
||||
{
|
||||
unsigned int count = 16; // max. num. of messages that will be read from the log
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2011 Gregory hainaut
|
||||
* Copyright (C) 2011-2013 Gregory hainaut
|
||||
* Copyright (C) 2007-2009 Gabest
|
||||
*
|
||||
* This Program is free software; you can redistribute it and/or modify
|
||||
|
@ -21,12 +21,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <fstream>
|
||||
#include "GSDevice.h"
|
||||
#include "GSTextureOGL.h"
|
||||
#include "GSdx.h"
|
||||
#include "GSVertexArrayOGL.h"
|
||||
#include "GSUniformBufferOGL.h"
|
||||
#include "GSShaderOGL.h"
|
||||
|
||||
class GSBlendStateOGL {
|
||||
// Note: You can also select the index of the draw buffer for which to set the blend setting
|
||||
|
@ -498,8 +498,6 @@ class GSDeviceOGL : public GSDevice
|
|||
GSVertexBufferStateOGL* m_vb; // vb_state for HW renderer
|
||||
GSVertexBufferStateOGL* m_vb_sr; // vb_state for StretchRect
|
||||
|
||||
bool m_debug_shader;
|
||||
|
||||
struct {
|
||||
GLuint ps[2]; // program object
|
||||
GSUniformBufferOGL* cb; // uniform buffer object
|
||||
|
@ -562,6 +560,8 @@ class GSDeviceOGL : public GSDevice
|
|||
GLenum draw;
|
||||
} m_state;
|
||||
|
||||
GSShaderOGL* m_shader;
|
||||
|
||||
GLuint m_vs[1<<5];
|
||||
GLuint m_gs[1<<3];
|
||||
GLuint m_ps_ss[1<<3];
|
||||
|
@ -629,8 +629,6 @@ class GSDeviceOGL : public GSDevice
|
|||
|
||||
GSTexture* Resolve(GSTexture* t);
|
||||
|
||||
void CompileShaderFromSource(const std::string& glsl_file, const std::string& entry, GLenum type, GLuint* program, const char* glsl_h_code, const std::string& macro_sel = "");
|
||||
|
||||
void EndScene();
|
||||
|
||||
void IASetPrimitiveTopology(GLenum topology);
|
||||
|
@ -642,13 +640,9 @@ class GSDeviceOGL : public GSDevice
|
|||
|
||||
void SetUniformBuffer(GSUniformBufferOGL* cb);
|
||||
|
||||
void VSSetShader(GLuint vs);
|
||||
void GSSetShader(GLuint gs);
|
||||
|
||||
void PSSetShaderResources(GSTexture* sr0, GSTexture* sr1);
|
||||
void PSSetShaderResource(int i, GSTexture* sr);
|
||||
void PSSetSamplerState(GLuint ss0, GLuint ss1, GLuint ss2 = 0);
|
||||
void PSSetShader(GLuint ps);
|
||||
|
||||
void OMSetFBO(GLuint fbo, GLenum buffer = GL_COLOR_ATTACHMENT0);
|
||||
void OMSetDepthStencilState(GSDepthStencilOGL* dss, uint8 sref);
|
||||
|
@ -671,7 +665,4 @@ class GSDeviceOGL : public GSDevice
|
|||
void SetupGS(GSSelector sel);
|
||||
void SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel);
|
||||
void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix);
|
||||
|
||||
hash_map<uint64, GLuint > m_single_prog;
|
||||
GLuint link_prog();
|
||||
};
|
||||
|
|
|
@ -0,0 +1,350 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2013 Gregory hainaut
|
||||
* Copyright (C) 2007-2009 Gabest
|
||||
*
|
||||
* 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; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "GSShaderOGL.h"
|
||||
|
||||
GSShaderOGL::GSShaderOGL(bool debug, bool sso, bool glsl420) :
|
||||
m_vs(0),
|
||||
m_ps(0),
|
||||
m_gs(0),
|
||||
m_prog(0),
|
||||
m_debug_shader(debug),
|
||||
m_sso(sso),
|
||||
m_glsl420(glsl420)
|
||||
{
|
||||
m_single_prog.clear();
|
||||
if (sso) {
|
||||
gl_GenProgramPipelines(1, &m_pipeline);
|
||||
gl_BindProgramPipeline(m_pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
GSShaderOGL::~GSShaderOGL()
|
||||
{
|
||||
if (m_sso)
|
||||
gl_DeleteProgramPipelines(1, &m_pipeline);
|
||||
|
||||
for (auto it = m_single_prog.begin(); it != m_single_prog.end() ; it++) gl_DeleteProgram(it->second);
|
||||
m_single_prog.clear();
|
||||
}
|
||||
|
||||
void GSShaderOGL::VS(GLuint s)
|
||||
{
|
||||
if (m_vs != s)
|
||||
{
|
||||
m_vs = s;
|
||||
if (m_sso)
|
||||
gl_UseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, s);
|
||||
}
|
||||
}
|
||||
|
||||
void GSShaderOGL::PS(GLuint s)
|
||||
{
|
||||
if (m_ps != s)
|
||||
{
|
||||
m_ps = s;
|
||||
if (m_sso)
|
||||
gl_UseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, s);
|
||||
}
|
||||
}
|
||||
|
||||
void GSShaderOGL::GS(GLuint s)
|
||||
{
|
||||
if (m_gs != s)
|
||||
{
|
||||
m_gs = s;
|
||||
if (m_sso)
|
||||
gl_UseProgramStages(m_pipeline, GL_GEOMETRY_SHADER_BIT, s);
|
||||
}
|
||||
}
|
||||
|
||||
void GSShaderOGL::SetUniformBinding(GLuint prog, GLchar* name, GLuint binding)
|
||||
{
|
||||
GLuint index;
|
||||
index = gl_GetUniformBlockIndex(prog, name);
|
||||
if (index != GL_INVALID_INDEX) {
|
||||
gl_UniformBlockBinding(prog, index, binding);
|
||||
}
|
||||
}
|
||||
|
||||
void GSShaderOGL::SetSamplerBinding(GLuint prog, GLchar* name, GLuint binding)
|
||||
{
|
||||
GLint loc = gl_GetUniformLocation(prog, name);
|
||||
if (loc != -1) {
|
||||
if (m_sso) {
|
||||
gl_ProgramUniform1i(prog, loc, binding);
|
||||
} else {
|
||||
gl_Uniform1i(loc, binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GSShaderOGL::SetupUniform()
|
||||
{
|
||||
if (m_glsl420) return;
|
||||
|
||||
if (m_sso) {
|
||||
SetUniformBinding(m_vs, "cb20", 20);
|
||||
SetUniformBinding(m_ps, "cb21", 21);
|
||||
|
||||
SetUniformBinding(m_ps, "cb10", 10);
|
||||
SetUniformBinding(m_ps, "cb11", 11);
|
||||
SetUniformBinding(m_ps, "cb12", 12);
|
||||
SetUniformBinding(m_ps, "cb13", 13);
|
||||
|
||||
SetSamplerBinding(m_ps, "TextureSampler", 0);
|
||||
SetSamplerBinding(m_ps, "PaletteSampler", 1);
|
||||
SetSamplerBinding(m_ps, "RTCopySampler", 2);
|
||||
} else {
|
||||
SetUniformBinding(m_prog, "cb20", 20);
|
||||
SetUniformBinding(m_prog, "cb21", 21);
|
||||
|
||||
SetUniformBinding(m_prog, "cb10", 10);
|
||||
SetUniformBinding(m_prog, "cb11", 11);
|
||||
SetUniformBinding(m_prog, "cb12", 12);
|
||||
SetUniformBinding(m_prog, "cb13", 13);
|
||||
|
||||
SetSamplerBinding(m_prog, "TextureSampler", 0);
|
||||
SetSamplerBinding(m_prog, "PaletteSampler", 1);
|
||||
SetSamplerBinding(m_prog, "RTCopySampler", 2);
|
||||
}
|
||||
}
|
||||
|
||||
bool GSShaderOGL::ValidateShader(GLuint s)
|
||||
{
|
||||
if (!m_debug_shader) return true;
|
||||
|
||||
GLint status;
|
||||
gl_GetShaderiv(s, GL_COMPILE_STATUS, &status);
|
||||
if (status) return true;
|
||||
|
||||
GLint log_length = 0;
|
||||
gl_GetShaderiv(s, GL_INFO_LOG_LENGTH, &log_length);
|
||||
if (log_length > 0) {
|
||||
char* log = new char[log_length];
|
||||
gl_GetShaderInfoLog(s, log_length, NULL, log);
|
||||
fprintf(stderr, "%s", log);
|
||||
delete[] log;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GSShaderOGL::ValidateProgram(GLuint p)
|
||||
{
|
||||
if (!m_debug_shader) return true;
|
||||
|
||||
GLint status;
|
||||
gl_GetProgramiv(p, GL_LINK_STATUS, &status);
|
||||
if (status) return true;
|
||||
|
||||
GLint log_length = 0;
|
||||
gl_GetProgramiv(p, GL_INFO_LOG_LENGTH, &log_length);
|
||||
if (log_length > 0) {
|
||||
char* log = new char[log_length];
|
||||
gl_GetProgramInfoLog(p, log_length, NULL, log);
|
||||
fprintf(stderr, "%s", log);
|
||||
delete[] log;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GSShaderOGL::ValidatePipeline(GLuint p)
|
||||
{
|
||||
if (!m_debug_shader) return true;
|
||||
|
||||
// FIXME: might be mandatory to validate the pipeline
|
||||
gl_ValidateProgramPipeline(p);
|
||||
|
||||
GLint status;
|
||||
gl_GetProgramPipelineiv(p, GL_VALIDATE_STATUS, &status);
|
||||
if (status) return true;
|
||||
|
||||
GLint log_length = 0;
|
||||
gl_GetProgramPipelineiv(p, GL_INFO_LOG_LENGTH, &log_length);
|
||||
if (log_length > 0) {
|
||||
char* log = new char[log_length];
|
||||
gl_GetProgramPipelineInfoLog(p, log_length, NULL, log);
|
||||
fprintf(stderr, "%s", log);
|
||||
delete[] log;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
GLuint GSShaderOGL::LinkNewProgram()
|
||||
{
|
||||
GLuint p = gl_CreateProgram();
|
||||
if (m_vs) gl_AttachShader(p, m_vs);
|
||||
if (m_ps) gl_AttachShader(p, m_ps);
|
||||
if (m_gs) gl_AttachShader(p, m_gs);
|
||||
|
||||
gl_LinkProgram(p);
|
||||
|
||||
ValidateProgram(p);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void GSShaderOGL::UseProgram()
|
||||
{
|
||||
hash_map<uint64, GLuint >::iterator it;
|
||||
if (!m_sso) {
|
||||
// Note: shader are integer lookup pointer. They start from 1 and incr
|
||||
// every time you create a new shader OR a new program.
|
||||
// Note2: vs & gs are precompiled at startup. FGLRX and radeon got value < 128.
|
||||
// We migth be able to pack the value in a 32bits int
|
||||
// I would need to check the behavior on Nvidia (pause/resume).
|
||||
uint64 sel = (uint64)m_vs << 40 | (uint64)m_gs << 20 | m_ps;
|
||||
it = m_single_prog.find(sel);
|
||||
if (it == m_single_prog.end()) {
|
||||
m_prog = LinkNewProgram();
|
||||
m_single_prog[sel] = m_prog;
|
||||
} else {
|
||||
m_prog = it->second;
|
||||
}
|
||||
|
||||
gl_UseProgram(m_prog);
|
||||
} else {
|
||||
ValidateProgram(m_pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
GLuint GSShaderOGL::Compile(const std::string& glsl_file, const std::string& entry, GLenum type, const char* glsl_h_code, const std::string& macro_sel)
|
||||
{
|
||||
// Not supported
|
||||
if (type == GL_GEOMETRY_SHADER && !GLLoader::found_geometry_shader) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// *****************************************************
|
||||
// Build a header string
|
||||
// *****************************************************
|
||||
// First select the version (must be the first line so we need to generate it
|
||||
std::string version;
|
||||
if (GLLoader::found_only_gl30) {
|
||||
version = "#version 130\n";
|
||||
} else {
|
||||
version = "#version 330\n";
|
||||
}
|
||||
if (m_glsl420) {
|
||||
version += "#extension GL_ARB_shading_language_420pack: require\n";
|
||||
} else {
|
||||
version += "#define DISABLE_GL42\n";
|
||||
}
|
||||
if (m_sso) {
|
||||
version += "#extension GL_ARB_separate_shader_objects : require\n";
|
||||
} else {
|
||||
if (!GLLoader::fglrx_buggy_driver)
|
||||
version += "#define DISABLE_SSO\n";
|
||||
}
|
||||
if (GLLoader::found_only_gl30) {
|
||||
// Need version 330
|
||||
version += "#extension GL_ARB_explicit_attrib_location : require\n";
|
||||
// Need version 140
|
||||
version += "#extension GL_ARB_uniform_buffer_object : require\n";
|
||||
}
|
||||
#ifdef ENABLE_OGL_STENCIL_DEBUG
|
||||
version += "#define ENABLE_OGL_STENCIL_DEBUG 1\n";
|
||||
#endif
|
||||
|
||||
// Allow to puts several shader in 1 files
|
||||
std::string shader_type;
|
||||
switch (type) {
|
||||
case GL_VERTEX_SHADER:
|
||||
shader_type = "#define VERTEX_SHADER 1\n";
|
||||
break;
|
||||
case GL_GEOMETRY_SHADER:
|
||||
shader_type = "#define GEOMETRY_SHADER 1\n";
|
||||
break;
|
||||
case GL_FRAGMENT_SHADER:
|
||||
shader_type = "#define FRAGMENT_SHADER 1\n";
|
||||
break;
|
||||
default: ASSERT(0);
|
||||
}
|
||||
|
||||
// Select the entry point ie the main function
|
||||
std::string entry_main = format("#define %s main\n", entry.c_str());
|
||||
|
||||
std::string header = version + shader_type + entry_main + macro_sel;
|
||||
|
||||
// Note it is better to separate header and source file to have the good line number
|
||||
// in the glsl compiler report
|
||||
const char** sources_array = (const char**)malloc(2*sizeof(char*));
|
||||
|
||||
char* header_str = (char*)malloc(header.size() + 1);
|
||||
sources_array[0] = header_str;
|
||||
header.copy(header_str, header.size(), 0);
|
||||
header_str[header.size()] = '\0';
|
||||
|
||||
if (glsl_h_code)
|
||||
sources_array[1] = glsl_h_code;
|
||||
else
|
||||
sources_array[1] = '\0';
|
||||
|
||||
|
||||
GLuint program;
|
||||
if (m_sso) {
|
||||
#if 0
|
||||
// Could be useful one day
|
||||
const GLchar* ShaderSource[1];
|
||||
ShaderSource[0] = header.append(source).c_str();
|
||||
program = gl_CreateShaderProgramv(type, 1, &ShaderSource[0]);
|
||||
#else
|
||||
program = gl_CreateShaderProgramv(type, 2, sources_array);
|
||||
#endif
|
||||
} else {
|
||||
program = gl_CreateShader(type);
|
||||
gl_ShaderSource(program, 2, sources_array, NULL);
|
||||
gl_CompileShader(program);
|
||||
}
|
||||
|
||||
free(header_str);
|
||||
free(sources_array);
|
||||
|
||||
bool status;
|
||||
if (m_sso)
|
||||
status = ValidateProgram(program);
|
||||
else
|
||||
status = ValidateShader(program);
|
||||
|
||||
if (!status) {
|
||||
// print extra info
|
||||
fprintf(stderr, "%s (entry %s, prog %d) :", glsl_file.c_str(), entry.c_str(), program);
|
||||
fprintf(stderr, "\n%s", macro_sel.c_str());
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
void GSShaderOGL::Delete(GLuint s)
|
||||
{
|
||||
if (m_sso) {
|
||||
gl_DeleteProgram(s);
|
||||
} else {
|
||||
gl_DeleteShader(s);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2013 Gregory hainaut
|
||||
* Copyright (C) 2007-2009 Gabest
|
||||
*
|
||||
* 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; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
class GSShaderOGL {
|
||||
GLuint m_pipeline;
|
||||
GLuint m_vs;
|
||||
GLuint m_ps;
|
||||
GLuint m_gs;
|
||||
GLuint m_prog;
|
||||
hash_map<uint64, GLuint > m_single_prog;
|
||||
const bool m_debug_shader;
|
||||
const bool m_sso;
|
||||
const bool m_glsl420;
|
||||
|
||||
|
||||
void SetUniformBinding(GLuint prog, GLchar* name, GLuint binding);
|
||||
void SetSamplerBinding(GLuint prog, GLchar* name, GLuint binding);
|
||||
|
||||
bool ValidateShader(GLuint p);
|
||||
bool ValidateProgram(GLuint p);
|
||||
bool ValidatePipeline(GLuint p);
|
||||
|
||||
GLuint LinkNewProgram();
|
||||
|
||||
public:
|
||||
GSShaderOGL(bool debug, bool sso, bool glsl420);
|
||||
~GSShaderOGL();
|
||||
|
||||
void GS(GLuint s);
|
||||
void PS(GLuint s);
|
||||
void VS(GLuint s);
|
||||
|
||||
void UseProgram();
|
||||
|
||||
void SetupUniform();
|
||||
|
||||
GLuint Compile(const std::string& glsl_file, const std::string& entry, GLenum type, const char* glsl_h_code, const std::string& macro_sel = "");
|
||||
void Delete(GLuint s);
|
||||
};
|
|
@ -48,11 +48,10 @@ void GSDeviceOGL::CreateTextureFX()
|
|||
m_vb = new GSVertexBufferStateOGL(sizeof(GSVertex), vert_format, countof(vert_format));
|
||||
|
||||
// Compile some dummy shaders to allow modification inside Apitrace for debug
|
||||
GLuint dummy;
|
||||
std::string macro = "\n";
|
||||
CompileShaderFromSource("tfx.glsl", "vs_main", GL_VERTEX_SHADER, &dummy, tfx_glsl, macro);
|
||||
CompileShaderFromSource("tfx.glsl", "gs_main", GL_GEOMETRY_SHADER, &dummy, tfx_glsl, macro);
|
||||
CompileShaderFromSource("tfx.glsl", "ps_main", GL_FRAGMENT_SHADER, &dummy, tfx_glsl, macro);
|
||||
m_shader->Compile("tfx.glsl", "vs_main", GL_VERTEX_SHADER, tfx_glsl, macro);
|
||||
m_shader->Compile("tfx.glsl", "gs_main", GL_GEOMETRY_SHADER, tfx_glsl, macro);
|
||||
m_shader->Compile("tfx.glsl", "ps_main", GL_FRAGMENT_SHADER, tfx_glsl, macro);
|
||||
|
||||
// Pre compile all Geometry & Vertex Shader
|
||||
// It might cost a seconds at startup but it would reduce benchmark pollution
|
||||
|
@ -72,20 +71,16 @@ void GSDeviceOGL::CreateTextureFX()
|
|||
|
||||
GLuint GSDeviceOGL::CompileVS(VSSelector sel)
|
||||
{
|
||||
GLuint vs;
|
||||
std::string macro = format("#define VS_BPPZ %d\n", sel.bppz)
|
||||
+ format("#define VS_LOGZ %d\n", sel.logz)
|
||||
+ format("#define VS_TME %d\n", sel.tme)
|
||||
+ format("#define VS_FST %d\n", sel.fst);
|
||||
|
||||
CompileShaderFromSource("tfx.glsl", "vs_main", GL_VERTEX_SHADER, &vs, tfx_glsl, macro);
|
||||
|
||||
return vs;
|
||||
return m_shader->Compile("tfx.glsl", "vs_main", GL_VERTEX_SHADER, tfx_glsl, macro);
|
||||
}
|
||||
|
||||
GLuint GSDeviceOGL::CompileGS(GSSelector sel)
|
||||
{
|
||||
GLuint gs;
|
||||
// Easy case
|
||||
if(! (sel.prim > 0 && (sel.iip == 0 || sel.prim == 3)))
|
||||
return 0;
|
||||
|
@ -93,9 +88,7 @@ GLuint GSDeviceOGL::CompileGS(GSSelector sel)
|
|||
std::string macro = format("#define GS_IIP %d\n", sel.iip)
|
||||
+ format("#define GS_PRIM %d\n", sel.prim);
|
||||
|
||||
CompileShaderFromSource("tfx.glsl", "gs_main", GL_GEOMETRY_SHADER, &gs, tfx_glsl, macro);
|
||||
|
||||
return gs;
|
||||
return m_shader->Compile("tfx.glsl", "gs_main", GL_GEOMETRY_SHADER, tfx_glsl, macro);
|
||||
}
|
||||
|
||||
GLuint GSDeviceOGL::CreateSampler(PSSamplerSelector sel)
|
||||
|
@ -166,8 +159,6 @@ GSBlendStateOGL* GSDeviceOGL::CreateBlend(OMBlendSelector bsel, uint8 afix)
|
|||
|
||||
GLuint GSDeviceOGL::CompilePS(PSSelector sel)
|
||||
{
|
||||
GLuint ps;
|
||||
|
||||
std::string macro = format("#define PS_FST %d\n", sel.fst)
|
||||
+ format("#define PS_WMS %d\n", sel.wms)
|
||||
+ format("#define PS_WMT %d\n", sel.wmt)
|
||||
|
@ -187,9 +178,7 @@ GLuint GSDeviceOGL::CompilePS(PSSelector sel)
|
|||
+ format("#define PS_TCOFFSETHACK %d\n", sel.tcoffsethack)
|
||||
+ format("#define PS_POINT_SAMPLER %d\n", sel.point_sampler);
|
||||
|
||||
CompileShaderFromSource("tfx.glsl", "ps_main", GL_FRAGMENT_SHADER, &ps, tfx_glsl, macro);
|
||||
|
||||
return ps;
|
||||
return m_shader->Compile("tfx.glsl", "ps_main", GL_FRAGMENT_SHADER, tfx_glsl, macro);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::SetupVS(VSSelector sel, const VSConstantBuffer* cb)
|
||||
|
@ -201,14 +190,14 @@ void GSDeviceOGL::SetupVS(VSSelector sel, const VSConstantBuffer* cb)
|
|||
m_vs_cb->upload(cb);
|
||||
}
|
||||
|
||||
VSSetShader(vs);
|
||||
m_shader->VS(vs);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::SetupGS(GSSelector sel)
|
||||
{
|
||||
GLuint gs = m_gs[sel];
|
||||
|
||||
GSSetShader(gs);
|
||||
m_shader->GS(gs);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel)
|
||||
|
@ -252,7 +241,7 @@ void GSDeviceOGL::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerS
|
|||
}
|
||||
|
||||
PSSetSamplerState(ss0, ss1, 0);
|
||||
PSSetShader(ps);
|
||||
m_shader->PS(ps);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix)
|
||||
|
|
|
@ -31,7 +31,6 @@ void GSWndGL::PopulateGlFunction()
|
|||
*(void**)&(gl_BindBufferBase) = GetProcAddress("glBindBufferBase");
|
||||
*(void**)&(gl_BindFragDataLocationIndexed) = GetProcAddress("glBindFragDataLocationIndexed");
|
||||
*(void**)&(gl_BindFramebuffer) = GetProcAddress("glBindFramebuffer");
|
||||
*(void**)&(gl_BindProgramPipeline) = GetProcAddress("glBindProgramPipeline");
|
||||
*(void**)&(gl_BindSampler) = GetProcAddress("glBindSampler");
|
||||
*(void**)&(gl_BindVertexArray) = GetProcAddress("glBindVertexArray");
|
||||
*(void**)&(gl_BlendEquationSeparate) = GetProcAddress("glBlendEquationSeparate");
|
||||
|
@ -49,7 +48,6 @@ void GSWndGL::PopulateGlFunction()
|
|||
*(void**)&(gl_DeleteBuffers) = GetProcAddress("glDeleteBuffers");
|
||||
*(void**)&(gl_DeleteFramebuffers) = GetProcAddress("glDeleteFramebuffers");
|
||||
*(void**)&(gl_DeleteProgram) = GetProcAddress("glDeleteProgram");
|
||||
*(void**)&(gl_DeleteProgramPipelines) = GetProcAddress("glDeleteProgramPipelines");
|
||||
*(void**)&(gl_DeleteSamplers) = GetProcAddress("glDeleteSamplers");
|
||||
*(void**)&(gl_DeleteShader) = GetProcAddress("glDeleteShader");
|
||||
*(void**)&(gl_DeleteVertexArrays) = GetProcAddress("glDeleteVertexArrays");
|
||||
|
@ -61,7 +59,6 @@ void GSWndGL::PopulateGlFunction()
|
|||
*(void**)&(gl_FramebufferTexture2D) = GetProcAddress("glFramebufferTexture2D");
|
||||
*(void**)&(gl_GenBuffers) = GetProcAddress("glGenBuffers");
|
||||
*(void**)&(gl_GenFramebuffers) = GetProcAddress("glGenFramebuffers");
|
||||
*(void**)&(gl_GenProgramPipelines) = GetProcAddress("glGenProgramPipelines");
|
||||
*(void**)&(gl_GenSamplers) = GetProcAddress("glGenSamplers");
|
||||
*(void**)&(gl_GenVertexArrays) = GetProcAddress("glGenVertexArrays");
|
||||
*(void**)&(gl_GetBufferParameteriv) = GetProcAddress("glGetBufferParameteriv");
|
||||
|
@ -87,6 +84,13 @@ void GSWndGL::PopulateGlFunction()
|
|||
*(void**)&(gl_VertexAttribPointer) = GetProcAddress("glVertexAttribPointer");
|
||||
*(void**)&(gl_TexStorage2D) = GetProcAddress("glTexStorage2D");
|
||||
*(void**)&(gl_BufferSubData) = GetProcAddress("glBufferSubData");
|
||||
// GL4.1
|
||||
*(void**)&(gl_BindProgramPipeline) = GetProcAddress("glBindProgramPipeline");
|
||||
*(void**)&(gl_DeleteProgramPipelines) = GetProcAddress("glDeleteProgramPipelines");
|
||||
*(void**)&(gl_GenProgramPipelines) = GetProcAddress("glGenProgramPipelines");
|
||||
*(void**)&(gl_GetProgramPipelineiv) = GetProcAddress("glGetProgramPipelineiv");
|
||||
*(void**)&(gl_GetProgramPipelineInfoLog) = GetProcAddress("glGetProgramPipelineInfoLog");
|
||||
*(void**)&(gl_ValidateProgramPipeline) = GetProcAddress("glValidateProgramPipeline");
|
||||
// NO GL4.1
|
||||
*(void**)&(gl_UseProgram) = GetProcAddress("glUseProgram");
|
||||
*(void**)&(gl_GetShaderInfoLog) = GetProcAddress("glGetShaderInfoLog");
|
||||
|
|
|
@ -599,6 +599,7 @@
|
|||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release SSE4|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release SSSE3|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GSShaderOGL.cpp" />
|
||||
<ClCompile Include="GSState.cpp" />
|
||||
<ClCompile Include="GSTables.cpp" />
|
||||
<ClCompile Include="GSTexture.cpp" />
|
||||
|
@ -1623,6 +1624,7 @@
|
|||
<ClInclude Include="GSSetting.h" />
|
||||
<ClInclude Include="GSSettingsDlg.h" />
|
||||
<ClInclude Include="GSSetupPrimCodeGenerator.h" />
|
||||
<ClInclude Include="GSShaderOGL.h" />
|
||||
<ClInclude Include="GSState.h" />
|
||||
<ClInclude Include="GSTables.h" />
|
||||
<ClInclude Include="GSTexture.h" />
|
||||
|
|
|
@ -126,6 +126,9 @@
|
|||
<ClCompile Include="GSSetupPrimCodeGenerator.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GSShaderOGL.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GSState.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -455,6 +458,9 @@
|
|||
<ClInclude Include="GSSetupPrimCodeGenerator.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GSShaderOGL.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GSState.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -766,6 +766,7 @@
|
|||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release SSE4|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release SSSE3|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GSShaderOGL.cpp" />
|
||||
<ClCompile Include="GSState.cpp" />
|
||||
<ClCompile Include="GSTables.cpp" />
|
||||
<ClCompile Include="GSTexture.cpp" />
|
||||
|
@ -1980,6 +1981,7 @@
|
|||
<ClInclude Include="GSSetting.h" />
|
||||
<ClInclude Include="GSSettingsDlg.h" />
|
||||
<ClInclude Include="GSSetupPrimCodeGenerator.h" />
|
||||
<ClInclude Include="GSShaderOGL.h" />
|
||||
<ClInclude Include="GSState.h" />
|
||||
<ClInclude Include="GSTables.h" />
|
||||
<ClInclude Include="GSTexture.h" />
|
||||
|
@ -2069,4 +2071,4 @@
|
|||
<UserProperties RESOURCE_FILE="GSdx.rc" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -126,6 +126,9 @@
|
|||
<ClCompile Include="GSSetupPrimCodeGenerator.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GSShaderOGL.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GSState.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -461,6 +464,9 @@
|
|||
<ClInclude Include="GSSetupPrimCodeGenerator.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GSShaderOGL.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GSState.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -740,4 +746,4 @@
|
|||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -1169,6 +1169,10 @@
|
|||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GSShaderOGL.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GSState.cpp"
|
||||
>
|
||||
|
@ -1603,6 +1607,10 @@
|
|||
RelativePath=".\GSSetupPrimCodeGenerator.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GSShaderOGL.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\GSState.h"
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue