|
|
@@ -405,138 +405,6 @@ void SwizzleFunc(const MortonSwizzleMode& mode, const SurfaceParams& params,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-MICROPROFILE_DEFINE(OpenGL_BlitSurface, "OpenGL", "BlitSurface", MP_RGB(128, 192, 64));
|
|
|
-static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface,
|
|
|
- GLuint read_fb_handle, GLuint draw_fb_handle, GLenum src_attachment = 0,
|
|
|
- GLenum dst_attachment = 0, std::size_t cubemap_face = 0) {
|
|
|
- MICROPROFILE_SCOPE(OpenGL_BlitSurface);
|
|
|
-
|
|
|
- const auto& src_params{src_surface->GetSurfaceParams()};
|
|
|
- const auto& dst_params{dst_surface->GetSurfaceParams()};
|
|
|
-
|
|
|
- OpenGLState prev_state{OpenGLState::GetCurState()};
|
|
|
- SCOPE_EXIT({ prev_state.Apply(); });
|
|
|
-
|
|
|
- OpenGLState state;
|
|
|
- state.draw.read_framebuffer = read_fb_handle;
|
|
|
- state.draw.draw_framebuffer = draw_fb_handle;
|
|
|
- // Set sRGB enabled if the destination surfaces need it
|
|
|
- state.framebuffer_srgb.enabled = dst_params.srgb_conversion;
|
|
|
- state.ApplyFramebufferState();
|
|
|
-
|
|
|
- u32 buffers{};
|
|
|
-
|
|
|
- if (src_params.type == SurfaceType::ColorTexture) {
|
|
|
- switch (src_params.target) {
|
|
|
- case SurfaceTarget::Texture2D:
|
|
|
- glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
|
|
|
- GL_TEXTURE_2D, src_surface->Texture().handle, 0);
|
|
|
- glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
|
|
|
- 0, 0);
|
|
|
- break;
|
|
|
- case SurfaceTarget::TextureCubemap:
|
|
|
- glFramebufferTexture2D(
|
|
|
- GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
|
|
|
- static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubemap_face),
|
|
|
- src_surface->Texture().handle, 0);
|
|
|
- glFramebufferTexture2D(
|
|
|
- GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
|
|
|
- static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubemap_face), 0, 0);
|
|
|
- break;
|
|
|
- case SurfaceTarget::Texture2DArray:
|
|
|
- glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
|
|
|
- src_surface->Texture().handle, 0, 0);
|
|
|
- glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0, 0, 0);
|
|
|
- break;
|
|
|
- case SurfaceTarget::Texture3D:
|
|
|
- glFramebufferTexture3D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
|
|
|
- SurfaceTargetToGL(src_params.target),
|
|
|
- src_surface->Texture().handle, 0, 0);
|
|
|
- glFramebufferTexture3D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
|
|
|
- SurfaceTargetToGL(src_params.target), 0, 0, 0);
|
|
|
- break;
|
|
|
- default:
|
|
|
- glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
|
|
|
- GL_TEXTURE_2D, src_surface->Texture().handle, 0);
|
|
|
- glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
|
|
|
- 0, 0);
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- switch (dst_params.target) {
|
|
|
- case SurfaceTarget::Texture2D:
|
|
|
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
|
|
|
- GL_TEXTURE_2D, dst_surface->Texture().handle, 0);
|
|
|
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
|
|
|
- 0, 0);
|
|
|
- break;
|
|
|
- case SurfaceTarget::TextureCubemap:
|
|
|
- glFramebufferTexture2D(
|
|
|
- GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
|
|
|
- static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubemap_face),
|
|
|
- dst_surface->Texture().handle, 0);
|
|
|
- glFramebufferTexture2D(
|
|
|
- GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
|
|
|
- static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubemap_face), 0, 0);
|
|
|
- break;
|
|
|
- case SurfaceTarget::Texture2DArray:
|
|
|
- glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
|
|
|
- dst_surface->Texture().handle, 0, 0);
|
|
|
- glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0, 0, 0);
|
|
|
- break;
|
|
|
-
|
|
|
- case SurfaceTarget::Texture3D:
|
|
|
- glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
|
|
|
- SurfaceTargetToGL(dst_params.target),
|
|
|
- dst_surface->Texture().handle, 0, 0);
|
|
|
- glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
|
|
|
- SurfaceTargetToGL(dst_params.target), 0, 0, 0);
|
|
|
- break;
|
|
|
- default:
|
|
|
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
|
|
|
- GL_TEXTURE_2D, dst_surface->Texture().handle, 0);
|
|
|
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
|
|
|
- 0, 0);
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- buffers = GL_COLOR_BUFFER_BIT;
|
|
|
- } else if (src_params.type == SurfaceType::Depth) {
|
|
|
- glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
|
|
|
- GL_TEXTURE_2D, 0, 0);
|
|
|
- glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
|
|
|
- src_surface->Texture().handle, 0);
|
|
|
- glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
|
|
|
-
|
|
|
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
|
|
|
- GL_TEXTURE_2D, 0, 0);
|
|
|
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
|
|
|
- dst_surface->Texture().handle, 0);
|
|
|
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
|
|
|
-
|
|
|
- buffers = GL_DEPTH_BUFFER_BIT;
|
|
|
- } else if (src_params.type == SurfaceType::DepthStencil) {
|
|
|
- glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment,
|
|
|
- GL_TEXTURE_2D, 0, 0);
|
|
|
- glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
|
|
|
- src_surface->Texture().handle, 0);
|
|
|
-
|
|
|
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment,
|
|
|
- GL_TEXTURE_2D, 0, 0);
|
|
|
- glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
|
|
|
- dst_surface->Texture().handle, 0);
|
|
|
-
|
|
|
- buffers = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
|
|
|
- }
|
|
|
-
|
|
|
- const auto& rect{src_params.GetRect()};
|
|
|
- glBlitFramebuffer(rect.left, rect.bottom, rect.right, rect.top, rect.left, rect.bottom,
|
|
|
- rect.right, rect.top, buffers,
|
|
|
- buffers == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST);
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
static void FastCopySurface(const Surface& src_surface, const Surface& dst_surface) {
|
|
|
const auto& src_params{src_surface->GetSurfaceParams()};
|
|
|
const auto& dst_params{dst_surface->GetSurfaceParams()};
|
|
|
@@ -1189,20 +1057,9 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& old_surface,
|
|
|
return new_surface;
|
|
|
}
|
|
|
|
|
|
- // If the format is the same, just do a framebuffer blit. This is significantly faster than
|
|
|
- // using PBOs. The is also likely less accurate, as textures will be converted rather than
|
|
|
- // reinterpreted. When use_accurate_gpu_emulation setting is enabled, perform a more accurate
|
|
|
- // surface copy, where pixels are reinterpreted as a new format (without conversion). This
|
|
|
- // code path uses OpenGL PBOs and is quite slow.
|
|
|
- const bool is_blit{old_params.pixel_format == new_params.pixel_format};
|
|
|
-
|
|
|
switch (new_params.target) {
|
|
|
case SurfaceTarget::Texture2D:
|
|
|
- if (is_blit) {
|
|
|
- BlitSurface(old_surface, new_surface, read_framebuffer.handle, draw_framebuffer.handle);
|
|
|
- } else {
|
|
|
- CopySurface(old_surface, new_surface, copy_pbo.handle);
|
|
|
- }
|
|
|
+ CopySurface(old_surface, new_surface, copy_pbo.handle);
|
|
|
break;
|
|
|
case SurfaceTarget::Texture3D:
|
|
|
AccurateCopySurface(old_surface, new_surface);
|