diff --git a/rpcs3/Emu/RSX/GL/GLHelpers.cpp b/rpcs3/Emu/RSX/GL/GLHelpers.cpp index a6fa97b252..92a1311b38 100644 --- a/rpcs3/Emu/RSX/GL/GLHelpers.cpp +++ b/rpcs3/Emu/RSX/GL/GLHelpers.cpp @@ -4,6 +4,7 @@ #include "GLCompute.h" #include "util/logs.hpp" +#include "../Common/simple_array.hpp" #include namespace gl @@ -223,8 +224,7 @@ namespace gl bool fbo::check() const { - save_binding_state save(*this); - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + GLenum status = DSA_CALL2_RET(CheckNamedFramebufferStatus, m_id, GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { @@ -245,29 +245,24 @@ namespace gl void fbo::draw_buffer(const attachment& buffer) const { - save_binding_state save(*this); GLenum buf = buffer.id(); - glDrawBuffers(1, &buf); + DSA_CALL3(NamedFramebufferDrawBuffers, FramebufferDrawBuffers, m_id, 1, &buf); } void fbo::draw_buffers(const std::initializer_list& indexes) const { - save_binding_state save(*this); - std::vector ids; + rsx::simple_array ids; ids.reserve(indexes.size()); for (auto &index : indexes) ids.push_back(index.id()); - glDrawBuffers(::narrow(ids.size()), ids.data()); + DSA_CALL3(NamedFramebufferDrawBuffers, FramebufferDrawBuffers, m_id, static_cast(ids.size()), ids.data()); } void fbo::read_buffer(const attachment& buffer) const { - save_binding_state save(*this); - GLenum buf = buffer.id(); - - glReadBuffer(buf); + DSA_CALL3(NamedFramebufferReadBuffer, FramebufferReadBuffer, m_id, buffer.id()); } void fbo::draw_arrays(rsx::primitive_type mode, GLsizei count, GLint first) const @@ -565,25 +560,25 @@ namespace gl { const bool is_depth_copy = (real_src->aspect() != image_aspect::color); const filter interp = (linear_interpolation && !is_depth_copy) ? filter::linear : filter::nearest; - GLenum attachment; + gl::fbo::attachment::type attachment; gl::buffers target; if (is_depth_copy) { if (real_dst->aspect() & gl::image_aspect::stencil) { - attachment = GL_DEPTH_STENCIL_ATTACHMENT; + attachment = fbo::attachment::type::depth_stencil; target = gl::buffers::depth_stencil; } else { - attachment = GL_DEPTH_ATTACHMENT; + attachment = fbo::attachment::type::depth; target = gl::buffers::depth; } } else { - attachment = GL_COLOR_ATTACHMENT0; + attachment = fbo::attachment::type::color; target = gl::buffers::color; } @@ -591,11 +586,11 @@ namespace gl save_binding_state saved; - glBindFramebuffer(GL_READ_FRAMEBUFFER, blit_src.id()); - glFramebufferTexture2D(GL_READ_FRAMEBUFFER, attachment, GL_TEXTURE_2D, real_src->id(), 0); + gl::fbo::attachment src_att{blit_src, static_cast(attachment)}; + src_att = *real_src; - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, blit_dst.id()); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D, real_dst->id(), 0); + gl::fbo::attachment dst_att{ blit_dst, static_cast(attachment) }; + dst_att = *real_dst; if (xfer_info.flip_horizontal) { @@ -607,13 +602,11 @@ namespace gl src_rect.flip_vertical(); } - glBlitFramebuffer(src_rect.x1, src_rect.y1, src_rect.x2, src_rect.y2, - dst_rect.x1, dst_rect.y1, dst_rect.x2, dst_rect.y2, - static_cast(target), static_cast(interp)); + blit_src.blit(blit_dst, src_rect, dst_rect, target, interp); // Release the attachments explicitly (not doing so causes glitches, e.g Journey Menu) - glFramebufferTexture2D(GL_READ_FRAMEBUFFER, attachment, GL_TEXTURE_2D, GL_NONE, 0); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, GL_TEXTURE_2D, GL_NONE, 0); + src_att = GL_NONE; + dst_att = GL_NONE; } if (xfer_info.dst_is_typeless) @@ -628,19 +621,19 @@ namespace gl save_binding_state saved; blit_dst.bind(); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst->id(), 0); + blit_dst.color[0] = *dst; blit_dst.check(); cmd->clear_color(color); cmd->color_maski(0, true, true, true, true); glClear(GL_COLOR_BUFFER_BIT); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, GL_NONE, 0); + blit_dst.color[0] = GL_NONE; } void blitter::fast_clear_image(gl::command_context& cmd, const texture* dst, float /*depth*/, u8 /*stencil*/) { - GLenum attachment; + fbo::attachment::type attachment; GLbitfield clear_mask; switch (const auto fmt = dst->get_internal_format()) @@ -648,27 +641,28 @@ namespace gl case texture::internal_format::depth16: case texture::internal_format::depth32f: clear_mask = GL_DEPTH_BUFFER_BIT; - attachment = GL_DEPTH_ATTACHMENT; + attachment = fbo::attachment::type::depth; break; case texture::internal_format::depth24_stencil8: case texture::internal_format::depth32f_stencil8: clear_mask = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; - attachment = GL_DEPTH_STENCIL_ATTACHMENT; + attachment = fbo::attachment::type::depth_stencil; break; default: fmt::throw_exception("Invalid texture passed to clear depth function, format=0x%x", static_cast(fmt)); } save_binding_state saved; + fbo::attachment attach_point{ blit_dst, attachment }; blit_dst.bind(); - glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, dst->id(), 0); + attach_point = *dst; blit_dst.check(); cmd->depth_mask(GL_TRUE); cmd->stencil_mask(0xFF); glClear(clear_mask); - glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, GL_NONE, 0); + attach_point = GL_NONE; } } diff --git a/rpcs3/Emu/RSX/GL/GLHelpers.h b/rpcs3/Emu/RSX/GL/GLHelpers.h index d3ae704d87..5bf8e00b6b 100644 --- a/rpcs3/Emu/RSX/GL/GLHelpers.h +++ b/rpcs3/Emu/RSX/GL/GLHelpers.h @@ -66,6 +66,12 @@ namespace gl gl##func(object_name, __VA_ARGS__) :\ gl##func##EXT(object_name, __VA_ARGS__) +#define DSA_CALL3(funcARB, funcDSA, ...)\ + if (::gl::get_driver_caps().ARB_dsa_supported)\ + gl##funcARB(__VA_ARGS__);\ + else\ + gl##funcDSA##EXT(__VA_ARGS__); + class fence; void enable_debugging(); @@ -2090,6 +2096,10 @@ public: GLuint m_id = GL_NONE; fbo &m_parent; + attachment(fbo& parent) + : m_parent(parent) + {} + public: attachment(fbo& parent, type type) : m_id(static_cast(type)) @@ -2120,25 +2130,21 @@ public: void operator = (const rbo& rhs) { - save_binding_state save(m_parent); m_parent.m_resource_bindings[m_id] = rhs.id(); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, m_id, GL_RENDERBUFFER, rhs.id()); + DSA_CALL2(NamedFramebufferRenderbuffer, m_parent.id(), m_id, GL_RENDERBUFFER, rhs.id()); } void operator = (const texture& rhs) { - save_binding_state save(m_parent); - ensure(rhs.get_target() == texture::target::texture2D); m_parent.m_resource_bindings[m_id] = rhs.id(); - glFramebufferTexture2D(GL_FRAMEBUFFER, m_id, GL_TEXTURE_2D, rhs.id(), 0); + DSA_CALL2(NamedFramebufferTexture, m_parent.id(), m_id, rhs.id(), 0); } void operator = (const GLuint rhs) { - save_binding_state save(m_parent); m_parent.m_resource_bindings[m_id] = rhs; - glFramebufferTexture2D(GL_FRAMEBUFFER, m_id, GL_TEXTURE_2D, rhs, 0); + DSA_CALL2(NamedFramebufferTexture, m_parent.id(), m_id, rhs, 0); } }; @@ -2167,10 +2173,18 @@ public: using attachment::operator =; }; + struct null_attachment : public attachment + { + null_attachment(fbo& parent) + : attachment(parent) + {} + }; + indexed_attachment color{ *this, attachment::type::color }; attachment depth{ *this, attachment::type::depth }; attachment stencil{ *this, attachment::type::stencil }; attachment depth_stencil{ *this, attachment::type::depth_stencil }; + null_attachment no_color{ *this }; enum class target { diff --git a/rpcs3/Emu/RSX/GL/GLOverlays.cpp b/rpcs3/Emu/RSX/GL/GLOverlays.cpp index 22426d51d9..453b8f5b20 100644 --- a/rpcs3/Emu/RSX/GL/GLOverlays.cpp +++ b/rpcs3/Emu/RSX/GL/GLOverlays.cpp @@ -77,28 +77,26 @@ namespace gl return; } - GLint old_fbo; GLint viewport[4]; + std::unique_ptr save_fbo; if (target_texture) { - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_fbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo.id()); + save_fbo = std::make_unique(fbo); if (depth_target) { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, target_texture, 0); - glDrawBuffer(GL_NONE); + fbo.draw_buffer(fbo.no_color); + fbo.depth_stencil = target_texture; } else { - GLenum buffer = GL_COLOR_ATTACHMENT0; - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target_texture, 0); - glDrawBuffers(1, &buffer); + fbo.color[0] = target_texture; + fbo.draw_buffer(fbo.color[0]); } } - if (!target_texture || glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) + if (!target_texture || fbo.check()) { // Set initial state glViewport(region.x1, region.y1, region.width(), region.height()); @@ -130,18 +128,13 @@ namespace gl bind_resources(); emit_geometry(); - // Clean up + glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); + if (target_texture) { - if (depth_target) - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); - else - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - - glBindFramebuffer(GL_FRAMEBUFFER, old_fbo); + fbo.color[0] = GL_NONE; + fbo.depth_stencil = GL_NONE; } - - glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); } else { diff --git a/rpcs3/Emu/RSX/GL/GLProcTable.h b/rpcs3/Emu/RSX/GL/GLProcTable.h index 77dbc97c1c..abc56f4fd6 100644 --- a/rpcs3/Emu/RSX/GL/GLProcTable.h +++ b/rpcs3/Emu/RSX/GL/GLProcTable.h @@ -147,12 +147,15 @@ OPENGL_PROC(PFNGLRENDERBUFFERSTORAGEPROC, RenderbufferStorage); OPENGL_PROC(PFNGLBINDFRAMEBUFFERPROC, BindFramebuffer); OPENGL_PROC(PFNGLDELETEFRAMEBUFFERSPROC, DeleteFramebuffers); OPENGL_PROC(PFNGLGENFRAMEBUFFERSPROC, GenFramebuffers); -OPENGL_PROC(PFNGLFRAMEBUFFERTEXTURE1DPROC, FramebufferTexture1D); -OPENGL_PROC(PFNGLFRAMEBUFFERTEXTURE2DPROC, FramebufferTexture2D); -OPENGL_PROC(PFNGLFRAMEBUFFERTEXTURE3DPROC, FramebufferTexture3D); -OPENGL_PROC(PFNGLFRAMEBUFFERRENDERBUFFERPROC, FramebufferRenderbuffer); OPENGL_PROC(PFNGLBLITFRAMEBUFFERPROC, BlitFramebuffer); -OPENGL_PROC(PFNGLDRAWBUFFERSPROC, DrawBuffers); +OPENGL_PROC(PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC, NamedFramebufferRenderbuffer); +OPENGL_PROC(PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC, NamedFramebufferRenderbufferEXT); +OPENGL_PROC(PFNGLNAMEDFRAMEBUFFERTEXTUREPROC, NamedFramebufferTexture); +OPENGL_PROC(PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC, NamedFramebufferTextureEXT); +OPENGL_PROC(PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC, NamedFramebufferDrawBuffers); +OPENGL_PROC(PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC, FramebufferDrawBuffersEXT); +OPENGL_PROC(PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC, NamedFramebufferReadBuffer); +OPENGL_PROC(PFNGLFRAMEBUFFERREADBUFFEREXTPROC, FramebufferReadBufferEXT); OPENGL_PROC(PFNGLENABLEIPROC, Enablei); OPENGL_PROC(PFNGLDISABLEIPROC, Disablei); @@ -166,7 +169,8 @@ OPENGL_PROC(PFNGLGETINTEGER64VPROC, GetInteger64v); OPENGL_PROC(PFNGLGETSTRINGIPROC, GetStringi); OPENGL_PROC(PFNGLGETINTEGERI_VPROC, GetIntegeri_v); -OPENGL_PROC(PFNGLCHECKFRAMEBUFFERSTATUSPROC, CheckFramebufferStatus); +OPENGL_PROC(PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC, CheckNamedFramebufferStatus); +OPENGL_PROC(PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC, CheckNamedFramebufferStatusEXT); OPENGL_PROC(PFNGLBINDBUFFERRANGEPROC, BindBufferRange); OPENGL_PROC(PFNGLBINDBUFFERBASEPROC, BindBufferBase);