diff --git a/plugins/GSdx/CMakeLists.txt b/plugins/GSdx/CMakeLists.txt index 1c8d9c7f05..17dd81805a 100644 --- a/plugins/GSdx/CMakeLists.txt +++ b/plugins/GSdx/CMakeLists.txt @@ -89,6 +89,7 @@ set(GSdxSources GSSetupPrimCodeGenerator.x64.avx.cpp GSSetupPrimCodeGenerator.x86.cpp GSSetupPrimCodeGenerator.x64.cpp + GSShaderOGL.cpp GSState.cpp GSTables.cpp GSTexture.cpp diff --git a/plugins/GSdx/GLLoader.cpp b/plugins/GSdx/GLLoader.cpp index 2f83173199..539fa99658 100644 --- a/plugins/GSdx/GLLoader.cpp +++ b/plugins/GSdx/GLLoader.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; diff --git a/plugins/GSdx/GLLoader.h b/plugins/GSdx/GLLoader.h index 2c3b958e72..1d45aeacab 100644 --- a/plugins/GSdx/GLLoader.h +++ b/plugins/GSdx/GLLoader.h @@ -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; diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index 03bb61101e..9c5717f2d7 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -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::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 diff --git a/plugins/GSdx/GSDeviceOGL.h b/plugins/GSdx/GSDeviceOGL.h index 2a7f5dcf1b..e35313a71c 100644 --- a/plugins/GSdx/GSDeviceOGL.h +++ b/plugins/GSdx/GSDeviceOGL.h @@ -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 #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 m_single_prog; - GLuint link_prog(); }; diff --git a/plugins/GSdx/GSShaderOGL.cpp b/plugins/GSdx/GSShaderOGL.cpp new file mode 100644 index 0000000000..ac59784f4b --- /dev/null +++ b/plugins/GSdx/GSShaderOGL.cpp @@ -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::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); + } +} diff --git a/plugins/GSdx/GSShaderOGL.h b/plugins/GSdx/GSShaderOGL.h new file mode 100644 index 0000000000..6ac603732e --- /dev/null +++ b/plugins/GSdx/GSShaderOGL.h @@ -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 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); +}; diff --git a/plugins/GSdx/GSTextureFXOGL.cpp b/plugins/GSdx/GSTextureFXOGL.cpp index 239c1629b5..be30c8bafc 100644 --- a/plugins/GSdx/GSTextureFXOGL.cpp +++ b/plugins/GSdx/GSTextureFXOGL.cpp @@ -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) diff --git a/plugins/GSdx/GSWnd.cpp b/plugins/GSdx/GSWnd.cpp index 779dc8a100..ebd801d7c7 100644 --- a/plugins/GSdx/GSWnd.cpp +++ b/plugins/GSdx/GSWnd.cpp @@ -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"); diff --git a/plugins/GSdx/GSdx.vcxproj b/plugins/GSdx/GSdx.vcxproj index 4289cf4322..21df4d28eb 100644 --- a/plugins/GSdx/GSdx.vcxproj +++ b/plugins/GSdx/GSdx.vcxproj @@ -599,6 +599,7 @@ true true + @@ -1623,6 +1624,7 @@ + diff --git a/plugins/GSdx/GSdx.vcxproj.filters b/plugins/GSdx/GSdx.vcxproj.filters index 7712fb7c28..93c1f8c355 100644 --- a/plugins/GSdx/GSdx.vcxproj.filters +++ b/plugins/GSdx/GSdx.vcxproj.filters @@ -126,6 +126,9 @@ Source Files + + Source Files + Source Files @@ -455,6 +458,9 @@ Header Files + + Header Files + Header Files diff --git a/plugins/GSdx/GSdx_vs11.vcxproj b/plugins/GSdx/GSdx_vs11.vcxproj index 7f797fb92c..321f1a172a 100644 --- a/plugins/GSdx/GSdx_vs11.vcxproj +++ b/plugins/GSdx/GSdx_vs11.vcxproj @@ -766,6 +766,7 @@ true true + @@ -1980,6 +1981,7 @@ + @@ -2069,4 +2071,4 @@ - \ No newline at end of file + diff --git a/plugins/GSdx/GSdx_vs11.vcxproj.filters b/plugins/GSdx/GSdx_vs11.vcxproj.filters index 379a6a1773..41a8ddf6b8 100644 --- a/plugins/GSdx/GSdx_vs11.vcxproj.filters +++ b/plugins/GSdx/GSdx_vs11.vcxproj.filters @@ -126,6 +126,9 @@ Source Files + + Source Files + Source Files @@ -461,6 +464,9 @@ Header Files + + Header Files + Header Files @@ -740,4 +746,4 @@ Resource Files - \ No newline at end of file + diff --git a/plugins/GSdx/GSdx_vs2008.vcproj b/plugins/GSdx/GSdx_vs2008.vcproj index 0b99690572..bc1501de0b 100644 --- a/plugins/GSdx/GSdx_vs2008.vcproj +++ b/plugins/GSdx/GSdx_vs2008.vcproj @@ -1169,6 +1169,10 @@ /> + + @@ -1603,6 +1607,10 @@ RelativePath=".\GSSetupPrimCodeGenerator.h" > + +