diff --git a/plugins/GSdx/CMakeLists.txt b/plugins/GSdx/CMakeLists.txt index 37658aef3d..cac8bfee05 100644 --- a/plugins/GSdx/CMakeLists.txt +++ b/plugins/GSdx/CMakeLists.txt @@ -8,8 +8,6 @@ endif(NOT TOP_CMAKE_WAS_SOURCED) # plugin name set(Output GSdx-0.1.16) -set(Replay pcsx2_GSReplayLoader) -set(Static GSdx-static) set(CommonFlags -D_LINUX @@ -186,10 +184,6 @@ include_directories(.) add_library(${Output} SHARED ${GSdxSources} ${GSdxHeaders}) -add_library(${Static} STATIC ${GSdxSources} ${GSdxHeaders}) - -add_executable(${Replay} linux_replay.cpp) - target_link_libraries(${Output} ${X11_LIBRARIES}) target_link_libraries(${Output} ${GLEW_LIBRARY}) target_link_libraries(${Output} ${OPENGL_LIBRARIES}) @@ -197,14 +191,37 @@ if(projectSDL) target_link_libraries(${Output} ${SDL_LIBRARY}) endif(projectSDL) -target_link_libraries(${Replay} ${OPENGL_LIBRARIES}) -target_link_libraries(${Replay} ${X11_LIBRARIES}) -target_link_libraries(${Replay} ${GLEW_LIBRARY}) -target_link_libraries(${Replay} ${GTK2_LIBRARIES}) -target_link_libraries(${Replay} ${Static}) -if(projectSDL) - target_link_libraries(${Replay} ${SDL_LIBRARY}) -endif(projectSDL) +if(NOT USER_CMAKE_LD_FLAGS STREQUAL "") + target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}") +endif(NOT USER_CMAKE_LD_FLAGS STREQUAL "") + +if(PACKAGE_MODE) + install(TARGETS ${Output} DESTINATION ${PLUGIN_DIR}) + + install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/convert.glsl DESTINATION ${PLUGIN_DIR}) + install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/interlace.glsl DESTINATION ${PLUGIN_DIR}) + install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/merge.glsl DESTINATION ${PLUGIN_DIR}) + install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/tfx.glsl DESTINATION ${PLUGIN_DIR}) +else(PACKAGE_MODE) + install(TARGETS ${Output} DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) + + install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/convert.glsl DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) + install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/interlace.glsl DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) + install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/merge.glsl DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) + install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/tfx.glsl DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) +endif(PACKAGE_MODE) + +################################### Replay Loader +set(Replay pcsx2_GSReplayLoader) +set(Static GSdx-static) + +# We can have separate option for gsdx inside the player. It will only +# cost a 2nd rebuild of gsdx... +#add_definitions(${CommonFlags} ${SDLFlags} ${OptimizationFlags} -W) + +add_library(${Static} STATIC ${GSdxSources} ${GSdxHeaders}) + +add_executable(${Replay} linux_replay.cpp) target_link_libraries(${Static} ${OPENGL_LIBRARIES}) target_link_libraries(${Static} ${X11_LIBRARIES}) @@ -214,26 +231,23 @@ if(projectSDL) target_link_libraries(${Static} ${SDL_LIBRARY}) endif(projectSDL) +target_link_libraries(${Replay} ${Static}) +# Warning others lib must be linked after GSdx... +target_link_libraries(${Replay} ${OPENGL_LIBRARIES}) +target_link_libraries(${Replay} ${X11_LIBRARIES}) +target_link_libraries(${Replay} ${GLEW_LIBRARY}) +target_link_libraries(${Replay} ${GTK2_LIBRARIES}) +if(projectSDL) + target_link_libraries(${Replay} ${SDL_LIBRARY}) +endif(projectSDL) + + if(NOT USER_CMAKE_LD_FLAGS STREQUAL "") target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}") endif(NOT USER_CMAKE_LD_FLAGS STREQUAL "") if(PACKAGE_MODE) install(TARGETS ${Replay} DESTINATION bin) - - install(TARGETS ${Output} DESTINATION ${PLUGIN_DIR}) - - install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/convert.glsl DESTINATION ${PLUGIN_DIR}) - install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/interlace.glsl DESTINATION ${PLUGIN_DIR}) - install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/merge.glsl DESTINATION ${PLUGIN_DIR}) - install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/tfx.glsl DESTINATION ${PLUGIN_DIR}) else(PACKAGE_MODE) install(TARGETS ${Replay} DESTINATION ${CMAKE_SOURCE_DIR}/bin) - - install(TARGETS ${Output} DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) - - install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/convert.glsl DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) - install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/interlace.glsl DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) - install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/merge.glsl DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) - install(FILES ${PROJECT_SOURCE_DIR}/plugins/GSdx/res/tfx.glsl DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) endif(PACKAGE_MODE) diff --git a/plugins/GSdx/GS.cpp b/plugins/GSdx/GS.cpp index bb5a8c5b4b..c65df40ef3 100644 --- a/plugins/GSdx/GS.cpp +++ b/plugins/GSdx/GS.cpp @@ -1205,13 +1205,14 @@ EXPORT_C GSReplay(char* lpszCmdLine, int renderer) packets.push_back(p); } - sleep(10); + sleep(1); // FIXME too slow :p // sleep(100); //while(IsWindowVisible(hWnd)) //FIXME map? - while(true) + bool finished = false; + while(!finished) { for(auto i = packets.begin(); i != packets.end(); i++) { @@ -1252,6 +1253,9 @@ EXPORT_C GSReplay(char* lpszCmdLine, int renderer) break; } } + + sleep(5); + finished = true; } for(auto i = packets.begin(); i != packets.end(); i++) @@ -1261,7 +1265,7 @@ EXPORT_C GSReplay(char* lpszCmdLine, int renderer) packets.clear(); - sleep(100); + sleep(1); GSclose(); GSshutdown(); diff --git a/plugins/GSdx/GSDeviceOGL.cpp b/plugins/GSdx/GSDeviceOGL.cpp index 742b9b078c..8f6753e718 100644 --- a/plugins/GSdx/GSDeviceOGL.cpp +++ b/plugins/GSdx/GSDeviceOGL.cpp @@ -45,22 +45,16 @@ //GL EXT: recompiling and managing multiple shaders, while still retaining most of //GL EXT: the performance of specialized shaders. // -// ************************** Uniform buffer -// // Note don't know how to chose block_binding_point (probably managed like texture unit -// maybe any number will be fine) -// index=glGetUniformBlockIndex(program, "BlockName"); -// glBindBufferBase(GL_UNIFORM_BUFFER, block_binding_point, some_buffer_object); -// glUniformBlockBinding(program, block_index, block_binding_point); -//#define LOUD_DEBUGGING +#define LOUD_DEBUGGING #define SHADER_DEBUG -//#define DUMP_START (70) -//#define DUMP_LENGTH (130) +#define DUMP_START (500) +#define DUMP_LENGTH (5) //#define PRINT_FRAME_NUMBER //#define ONLY_LINES // It seems dual blending does not work on AMD !!! -//#define DISABLE_DUAL_BLEND +#define DISABLE_DUAL_BLEND #ifdef DUMP_START static uint32 g_draw_count = 0; @@ -73,13 +67,14 @@ GSDeviceOGL::GSDeviceOGL() , m_window(NULL) , m_pipeline(0) , m_fbo(0) + , m_fbo_read(0) , m_vb_sr(NULL) , m_srv_changed(false) , m_ss_changed(false) { m_msaa = theApp.GetConfig("msaa", 0); - memset(&m_merge, 0, sizeof(m_merge)); + memset(&m_merge_obj, 0, sizeof(m_merge_obj)); memset(&m_interlace, 0, sizeof(m_interlace)); memset(&m_convert, 0, sizeof(m_convert)); memset(&m_date, 0, sizeof(m_date)); @@ -91,11 +86,11 @@ GSDeviceOGL::~GSDeviceOGL() // Clean vertex buffer state delete (m_vb_sr); - // Clean m_merge + // Clean m_merge_obj for (uint i = 0; i < 2; i++) - glDeleteProgram(m_merge.ps[i]); - delete (m_merge.cb); - delete (m_merge.bs); + glDeleteProgram(m_merge_obj.ps[i]); + delete (m_merge_obj.cb); + delete (m_merge_obj.bs); // Clean m_interlace for (uint i = 0; i < 2; i++) @@ -118,6 +113,7 @@ GSDeviceOGL::~GSDeviceOGL() // Clean various opengl allocation glDeleteProgramPipelines(1, &m_pipeline); glDeleteFramebuffers(1, &m_fbo); + glDeleteFramebuffers(1, &m_fbo_read); // Delete HW FX delete m_vs_cb; @@ -141,7 +137,7 @@ GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int for { // A wrapper to call GSTextureOGL, with the different kind of parameter GSTextureOGL* t = NULL; - t = new GSTextureOGL(type, w, h, msaa, format); + t = new GSTextureOGL(type, w, h, msaa, format, m_fbo_read); switch(type) { @@ -234,6 +230,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd) glBindProgramPipeline(m_pipeline); glGenFramebuffers(1, &m_fbo); + glGenFramebuffers(1, &m_fbo_read); // Setup FBO fragment output // OMSetFBO(m_fbo); // glDrawBuffer(GL_COLOR_ATTACHMENT0); @@ -312,14 +309,14 @@ bool GSDeviceOGL::Create(GSWnd* wnd) // **************************************************************** // merge // **************************************************************** - m_merge.cb = new GSUniformBufferOGL(1, sizeof(MergeConstantBuffer)); + m_merge_obj.cb = new GSUniformBufferOGL(1, sizeof(MergeConstantBuffer)); - for(int i = 0; i < countof(m_merge.ps); i++) - CompileShaderFromSource("merge.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &m_merge.ps[i]); + for(int 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]); - m_merge.bs = new GSBlendStateOGL(); - m_merge.bs->EnableBlend(); - m_merge.bs->SetRGB(GL_FUNC_ADD, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + m_merge_obj.bs = new GSBlendStateOGL(); + m_merge_obj.bs->EnableBlend(); + m_merge_obj.bs->SetRGB(GL_FUNC_ADD, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // **************************************************************** // interlace @@ -508,7 +505,7 @@ bool GSDeviceOGL::Reset(int w, int h) // Opengl allocate the backbuffer with the window. The render is done in the backbuffer when // there isn't any FBO. Only a dummy texture is created to easily detect when the rendering is done // in the backbuffer - m_backbuffer = new GSTextureOGL(GSTextureOGL::Backbuffer, w, h, false, 0); + m_backbuffer = new GSTextureOGL(GSTextureOGL::Backbuffer, w, h, false, 0, m_fbo_read); return true; } @@ -542,7 +539,8 @@ void GSDeviceOGL::DrawPrimitive() m_state.ps_srv[i]->Save(format("/tmp/in_%d__%d.bmp", g_draw_count, i)); } } - if (m_state.dsv != NULL) m_state.dsv->Save(format("/tmp/ds_in_%d.bmp", g_draw_count)); + if (m_state.rtv != NULL) m_state.rtv->Save(format("/tmp/in_current_out_%d.bmp", g_draw_count)); + //if (m_state.dsv != NULL) m_state.dsv->Save(format("/tmp/ds_in_%d.bmp", g_draw_count)); fprintf(stderr, "Draw %d (Frame %d)\n", g_draw_count, g_frame_count); fprintf(stderr, "vs: %d ; gs: %d ; ps: %d\n", m_state.vs, m_state.gs, m_state.ps); @@ -558,7 +556,7 @@ void GSDeviceOGL::DrawPrimitive() #ifdef DUMP_START if ( dump_me ) { if (m_state.rtv != NULL) m_state.rtv->Save(format("/tmp/out_%d.bmp", g_draw_count)); - if (m_state.dsv != NULL) m_state.dsv->Save(format("/tmp/ds_out_%d.bmp", g_draw_count)); + //if (m_state.dsv != NULL) m_state.dsv->Save(format("/tmp/ds_out_%d.bmp", g_draw_count)); fprintf(stderr, "\n"); @@ -849,15 +847,15 @@ void GSDeviceOGL::DoMerge(GSTexture* st[2], GSVector4* sr, GSTexture* dt, GSVect if(st[1] && !slbg) { - StretchRect(st[1], sr[1], dt, dr[1], m_merge.ps[0]); + StretchRect(st[1], sr[1], dt, dr[1], m_merge_obj.ps[0]); } if(st[0]) { - SetUniformBuffer(m_merge.cb); - m_merge.cb->upload(&c.v); + SetUniformBuffer(m_merge_obj.cb); + m_merge_obj.cb->upload(&c.v); - StretchRect(st[0], sr[0], dt, dr[0], m_merge.ps[mmod ? 1 : 0], m_merge.bs); + StretchRect(st[0], sr[0], dt, dr[0], m_merge_obj.ps[mmod ? 1 : 0], m_merge_obj.bs); } } diff --git a/plugins/GSdx/GSDeviceOGL.h b/plugins/GSdx/GSDeviceOGL.h index 2e727d3922..cd10698802 100644 --- a/plugins/GSdx/GSDeviceOGL.h +++ b/plugins/GSdx/GSDeviceOGL.h @@ -41,6 +41,7 @@ class GSBlendStateOGL { bool m_g_msk; bool m_a_msk; bool constant_factor; + float debug_factor; public: @@ -55,7 +56,7 @@ public: , m_b_msk(GL_TRUE) , m_g_msk(GL_TRUE) , m_a_msk(GL_TRUE) - , constant_factor(true) + , constant_factor(false) {} void SetRGB(GLenum op, GLenum src, GLenum dst) @@ -100,7 +101,10 @@ public: if (m_enable) { glEnable(GL_BLEND); - if (HasConstantFactor()) glBlendColor(factor, factor, factor, 0); + if (HasConstantFactor()) { + debug_factor = factor; + glBlendColor(factor, factor, factor, 0); + } glBlendEquationSeparate(m_equation_RGB, m_equation_ALPHA); glBlendFuncSeparate(m_func_sRGB, m_func_dRGB, m_func_sALPHA, m_func_dALPHA); @@ -135,6 +139,7 @@ public: { if (!m_enable) return; fprintf(stderr,"Blend op: %s; src:%s; dst:%s\n", NameOfParam(m_equation_RGB), NameOfParam(m_func_sRGB), NameOfParam(m_func_dRGB)); + if (HasConstantFactor()) fprintf(stderr, "Blend constant: %f\n", debug_factor); fprintf(stderr,"Mask. R:%d B:%d G:%d A:%d\n", m_r_msk, m_b_msk, m_g_msk, m_a_msk); } }; @@ -315,10 +320,12 @@ public: void upload(const void* src, uint32 count) { +#ifdef OGL_DEBUG GLint b_size = -1; glGetBufferParameteriv(m_target, GL_BUFFER_SIZE, &b_size); if (b_size <= 0) return; +#endif m_count = count; @@ -345,10 +352,12 @@ public: // Upload the data to the buffer uint8* dst = (uint8*) glMapBufferRange(m_target, m_stride*m_start, m_stride*m_count, map_flags); +#ifdef OGL_DEBUG if (dst == NULL) { fprintf(stderr, "CRITICAL ERROR map failed for vb!!!\n"); return; } +#endif memcpy(dst, src, m_stride*m_count); glUnmapBuffer(m_target); } @@ -412,7 +421,7 @@ public: topo = "triangle strip"; break; } - fprintf(stderr, "%d elements of %s\n", element, topo.c_str()); + fprintf(stderr, "%d primitives of %s\n", element, topo.c_str()); } }; @@ -661,6 +670,7 @@ class GSDeviceOGL : public GSDevice GLuint m_pipeline; // pipeline to attach program shader GLuint m_fbo; // frame buffer container + GLuint m_fbo_read; // frame buffer container only for reading GSVertexBufferStateOGL* m_vb; // vb_state for HW renderer GSVertexBufferStateOGL* m_vb_sr; // vb_state for StretchRect @@ -669,7 +679,7 @@ class GSDeviceOGL : public GSDevice GLuint ps[2]; // program object GSUniformBufferOGL* cb; // uniform buffer object GSBlendStateOGL* bs; - } m_merge; + } m_merge_obj; struct { GLuint ps[4]; // program object diff --git a/plugins/GSdx/GSTextureOGL.cpp b/plugins/GSdx/GSTextureOGL.cpp index 269da857b6..f7ff075ccc 100644 --- a/plugins/GSdx/GSTextureOGL.cpp +++ b/plugins/GSdx/GSTextureOGL.cpp @@ -25,23 +25,13 @@ static int g_state_texture_unit = -1; static int g_state_texture_id = -1; -GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format) +GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint fbo_read) : m_extra_buffer_id(0), m_pbo_size(0) { // ************************************************************* // Opengl world - // http://www.opengl.org/wiki/Renderbuffer_Object - // render: constructor -> glGenRenderbuffers, glDeleteRenderbuffers - // info -> glGetRenderbufferParameteriv, glIsRenderbuffer - // binding -> glBindRenderbuffer (only 1 target), glFramebufferRenderbuffer (attach actually) - // setup param -> glRenderbufferStorageMultisample (after this call the buffer is unitialized) - // - // the only way to use a renderbuffer object is to attach it to a Framebuffer Object. After you bind that - // FBO to the context, and set up the draw or read buffers appropriately, you can use pixel transfer operations - // to read and write to it. Of course, you can also render to it. The standard glClear function will also clear the appropriate buffer. - // // Render work in parallal with framebuffer object (FBO) http://www.opengl.org/wiki/Framebuffer_Objects // render are attached to FBO through : glFramebufferRenderbuffer. You can query the number of colorattachement with GL_MAX_COLOR_ATTACHMENTS // FBO : constructor -> glGenFramebuffers, glDeleteFramebuffers @@ -57,28 +47,13 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format) // glReadBuffer // glBlitFramebuffer - // TODO: we can render directly into a texture so I'm not sure rendertarget are useful anymore !!! // ************************************************************* m_size.x = w; m_size.y = h; m_format = format; m_type = type; m_msaa = msaa; - - // == Then generate the texture or buffer. - // D3D11_BIND_RENDER_TARGET: Bind a texture as a render target for the output-merger stage. - // => glGenRenderbuffers with GL_COLOR_ATTACHMENTi (Hum glGenTextures might work too) - // D3D11_BIND_DEPTH_STENCIL: Bind a texture as a depth-stencil target for the output-merger stage. - // => glGenRenderbuffers with GL_DEPTH_STENCIL_ATTACHMENT - // D3D11_BIND_SHADER_RESOURCE: Bind a buffer or texture to a shader stage - // => glGenTextures - // D3D11_USAGE_STAGING: A resource that supports data transfer (copy) from the GPU to the CPU. - // glGenTextures - // glReadPixels seems to use a framebuffer. In this case you can setup the source - // with glReadBuffer(GL_COLOR_ATTACHMENTi) - // glGetTexImage: read pixels of a bound texture - // => To allow map/unmap. I think we can use a pixel buffer (target GL_PIXEL_UNPACK_BUFFER) - // http://www.opengl.org/wiki/Pixel_Buffer_Objects + m_fbo_read = fbo_read; // Generate the buffer switch (m_type) { @@ -396,8 +371,15 @@ bool GSTextureOGL::Save(const string& fn, bool dds) EnableUnit(1); glGetTexImage(m_texture_target, 0, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, image); } else { - EnableUnit(0); - glGetTexImage(m_texture_target, 0, GL_RGBA, GL_UNSIGNED_BYTE, image); + glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read); + + EnableUnit(1); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, m_texture_target, m_texture_id, 0); + + glReadBuffer(GL_COLOR_ATTACHMENT1); + glReadPixels(0, 0, m_size.x, m_size.y, GL_RGBA, GL_UNSIGNED_BYTE, image); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); } Save(fn, image, pitch); diff --git a/plugins/GSdx/GSTextureOGL.h b/plugins/GSdx/GSTextureOGL.h index 92c9010928..3842842b15 100644 --- a/plugins/GSdx/GSTextureOGL.h +++ b/plugins/GSdx/GSTextureOGL.h @@ -30,9 +30,10 @@ class GSTextureOGL : public GSTexture GLuint m_texture_id; // the texture id uint m_extra_buffer_id; int m_pbo_size; + GLuint m_fbo_read; public: - explicit GSTextureOGL(int type, int w, int h, bool msaa, int format); + explicit GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint fbo_read); virtual ~GSTextureOGL(); bool Update(const GSVector4i& r, const void* data, int pitch); diff --git a/plugins/GSdx/GSWnd.cpp b/plugins/GSdx/GSWnd.cpp index 75147c4eb6..c4a17a1920 100644 --- a/plugins/GSdx/GSWnd.cpp +++ b/plugins/GSdx/GSWnd.cpp @@ -572,7 +572,7 @@ GSVector4i GSWnd::GetClientRect() bool GSWnd::SetWindowText(const char* title) { -#if ENABLE_SDL_DEV +#ifdef ENABLE_SDL_DEV if (!m_managed) return true; // Do not find anyway to check the current fullscreen status