diff --git a/src/common/math_util.h b/src/common/math_util.h index 382d0197d..d7cb94a82 100644 --- a/src/common/math_util.h +++ b/src/common/math_util.h @@ -23,6 +23,8 @@ struct Rectangle { constexpr Rectangle(T left, T top, T right, T bottom) : left(left), top(top), right(right), bottom(bottom) {} + auto operator<=>(const Rectangle&) const = default; + [[nodiscard]] T GetWidth() const { return std::abs(static_cast>(right - left)); } diff --git a/src/video_core/rasterizer_cache/cached_surface.cpp b/src/video_core/rasterizer_cache/cached_surface.cpp index 0f72be26b..98421a484 100644 --- a/src/video_core/rasterizer_cache/cached_surface.cpp +++ b/src/video_core/rasterizer_cache/cached_surface.cpp @@ -6,12 +6,14 @@ #include "common/scope_exit.h" #include "common/texture.h" #include "core/core.h" +#include "core/settings.h" #include "video_core/rasterizer_cache/cached_surface.h" -#include "video_core/rasterizer_cache/morton_swizzle.h" #include "video_core/rasterizer_cache/rasterizer_cache.h" #include "video_core/renderer_opengl/gl_state.h" +#include "video_core/renderer_opengl/gl_vars.h" #include "video_core/renderer_opengl/texture_downloader_es.h" #include "video_core/renderer_opengl/texture_filters/texture_filterer.h" +#include "video_core/video_core.h" namespace OpenGL { @@ -337,8 +339,17 @@ void CachedSurface::UploadGLTexture(Common::Rectangle rect) { const Common::Rectangle from_rect{0, height, width, 0}; if (!owner.texture_filterer->Filter(unscaled_tex, from_rect, texture, scaled_rect, type)) { - const Aspect aspect = ToAspect(type); - runtime.BlitTextures(unscaled_tex, {aspect, from_rect}, texture, {aspect, scaled_rect}); + const Subresource src_subresource = { + .type = type, + .region = from_rect + }; + + const Subresource dst_subresource = { + .type = type, + .region = scaled_rect + }; + + runtime.BlitTextures(unscaled_tex, src_subresource, texture, dst_subresource); } } @@ -370,7 +381,6 @@ void CachedSurface::DownloadGLTexture(const Common::Rectangle& rect) { const FormatTuple& tuple = GetFormatTuple(pixel_format); // If not 1x scale, blit scaled texture to a new 1x texture and use that to flush - const Aspect aspect = ToAspect(type); if (res_scale != 1) { auto scaled_rect = rect; scaled_rect.left *= res_scale; @@ -380,9 +390,19 @@ void CachedSurface::DownloadGLTexture(const Common::Rectangle& rect) { const Common::Rectangle unscaled_tex_rect{0, rect.GetHeight(), rect.GetWidth(), 0}; auto unscaled_tex = owner.AllocateSurfaceTexture(pixel_format, rect.GetWidth(), rect.GetHeight()); + + const Subresource src_subresource = { + .type = type, + .region = scaled_rect + }; + + const Subresource dst_subresource = { + .type = type, + .region = unscaled_tex_rect + }; + // Blit scaled texture to the unscaled one - runtime.BlitTextures(texture, {aspect, scaled_rect}, unscaled_tex, - {aspect, unscaled_tex_rect}); + runtime.BlitTextures(texture, src_subresource, unscaled_tex, dst_subresource); state.texture_units[0].texture_2d = unscaled_tex.handle; state.Apply(); @@ -396,7 +416,12 @@ void CachedSurface::DownloadGLTexture(const Common::Rectangle& rect) { glGetTexImage(GL_TEXTURE_2D, 0, tuple.format, tuple.type, &gl_buffer[buffer_offset]); } } else { - runtime.ReadTexture(texture, {aspect, rect}, tuple, gl_buffer.data()); + const Subresource subresource = { + .type = type, + .region = rect + }; + + runtime.ReadTexture(texture, subresource, tuple, gl_buffer.data()); } glPixelStorei(GL_PACK_ROW_LENGTH, 0); diff --git a/src/video_core/rasterizer_cache/rasterizer_cache.cpp b/src/video_core/rasterizer_cache/rasterizer_cache.cpp index 194ad72c6..ff5f9ab09 100644 --- a/src/video_core/rasterizer_cache/rasterizer_cache.cpp +++ b/src/video_core/rasterizer_cache/rasterizer_cache.cpp @@ -48,9 +48,8 @@ void RasterizerCache::CopySurface(const Surface& src_surface, const Surface& dst SurfaceParams subrect_params = dst_surface->FromInterval(copy_interval); ASSERT(subrect_params.GetInterval() == copy_interval && src_surface != dst_surface); - const Aspect aspect = ToAspect(dst_surface->type); const Subresource dst_subresource = { - .aspect = aspect, + .type = dst_surface->type, .region = dst_surface->GetScaledSubRect(subrect_params) }; @@ -66,7 +65,7 @@ void RasterizerCache::CopySurface(const Surface& src_surface, const Surface& dst } const ClearValue clear_value = - MakeClearValue(aspect, dst_surface->pixel_format, fill_buffer.data()); + MakeClearValue(dst_surface->type, dst_surface->pixel_format, fill_buffer.data()); runtime.ClearTexture(dst_surface->texture, dst_subresource, clear_value); return; @@ -74,7 +73,7 @@ void RasterizerCache::CopySurface(const Surface& src_surface, const Surface& dst if (src_surface->CanSubRect(subrect_params)) { const Subresource src_subresource = { - .aspect = aspect, + .type = src_surface->type, .region = src_surface->GetScaledSubRect(subrect_params) }; @@ -209,14 +208,13 @@ bool RasterizerCache::BlitSurfaces(const Surface& src_surface, if (CheckFormatsBlittable(src_surface->pixel_format, dst_surface->pixel_format)) { dst_surface->InvalidateAllWatcher(); - const Aspect aspect = ToAspect(src_surface->type); const Subresource src_subresource = { - .aspect = aspect, + .type = src_surface->type, .region = src_rect }; const Subresource dst_subresource = { - .aspect = aspect, + .type = dst_surface->type, .region = dst_rect }; @@ -441,14 +439,13 @@ Surface RasterizerCache::GetTextureSurface(const Pica::Texture::TextureInfo& inf } if (!surface->is_custom && texture_filterer->IsNull()) { - const Aspect aspect = ToAspect(surface->type); const Subresource src_subresource = { - .aspect = aspect, + .type = surface->type, .region = level_surface->GetScaledRect() }; const Subresource dst_subresource = { - .aspect = aspect, + .type = surface->type, .region = surface_params.GetScaledRect(), .level = level }; @@ -531,14 +528,13 @@ const CachedTextureCube& RasterizerCache::GetTextureCube(const TextureCubeConfig ValidateSurface(surface, surface->addr, surface->size); } - const Aspect aspect = ToAspect(surface->type); const Subresource src_subresource = { - .aspect = aspect, + .type = surface->type, .region = surface->GetScaledRect() }; const Subresource dst_subresource = { - .aspect = aspect, + .type = surface->type, .region = Common::Rectangle{0, scaled_size, scaled_size, 0} }; @@ -862,14 +858,13 @@ bool RasterizerCache::ValidateByReinterpretation(const Surface& surface, if (!texture_filterer->Filter(tmp_tex, tmp_rect, surface->texture, dest_rect, type)) { - const Aspect aspect = ToAspect(type); const Subresource src_subresource = { - .aspect = aspect, + .type = type, .region = tmp_rect }; const Subresource dst_subresource = { - .aspect = aspect, + .type = type, .region = dest_rect }; diff --git a/src/video_core/rasterizer_cache/texture_runtime.cpp b/src/video_core/rasterizer_cache/texture_runtime.cpp index 03d923265..c73f28ef0 100644 --- a/src/video_core/rasterizer_cache/texture_runtime.cpp +++ b/src/video_core/rasterizer_cache/texture_runtime.cpp @@ -9,15 +9,21 @@ namespace OpenGL { -GLbitfield ToBufferMask(Aspect aspect) { - switch (aspect) { - case Aspect::Color: +GLbitfield MakeBufferMask(SurfaceType type) { + switch (type) { + case SurfaceType::Color: + case SurfaceType::Texture: + case SurfaceType::Fill: return GL_COLOR_BUFFER_BIT; - case Aspect::Depth: + case SurfaceType::Depth: return GL_DEPTH_BUFFER_BIT; - case Aspect::DepthStencil: + case SurfaceType::DepthStencil: return GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; + default: + UNREACHABLE_MSG("Invalid surface type!"); } + + return GL_COLOR_BUFFER_BIT; } TextureRuntime::TextureRuntime() { @@ -37,24 +43,28 @@ void TextureRuntime::ReadTexture(const OGLTexture& tex, Subresource subresource, state.Apply(); const u32 level = subresource.level; - switch (subresource.aspect) { - case Aspect::Color: + switch (subresource.type) { + case SurfaceType::Color: + case SurfaceType::Texture: + case SurfaceType::Fill: glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex.handle, level); glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); break; - case Aspect::Depth: + case SurfaceType::Depth: glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tex.handle, level); glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); break; - case Aspect::DepthStencil: + case SurfaceType::DepthStencil: glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, tex.handle, level); break; + default: + UNREACHABLE_MSG("Invalid surface type!"); } const auto& rect = subresource.region; @@ -79,8 +89,10 @@ bool TextureRuntime::ClearTexture(const OGLTexture& tex, Subresource subresource state.Apply(); const u32 level = subresource.level; - switch (subresource.aspect) { - case Aspect::Color: + switch (subresource.type) { + case SurfaceType::Color: + case SurfaceType::Texture: + case SurfaceType::Fill: glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex.handle, level); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, @@ -94,7 +106,7 @@ bool TextureRuntime::ClearTexture(const OGLTexture& tex, Subresource subresource glClearBufferfv(GL_COLOR, 0, value.color.AsArray()); break; - case Aspect::Depth: + case SurfaceType::Depth: glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tex.handle, level); @@ -105,7 +117,7 @@ bool TextureRuntime::ClearTexture(const OGLTexture& tex, Subresource subresource glClearBufferfv(GL_DEPTH, 0, &value.depth); break; - case Aspect::DepthStencil: + case SurfaceType::DepthStencil: glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, tex.handle, level); @@ -116,6 +128,8 @@ bool TextureRuntime::ClearTexture(const OGLTexture& tex, Subresource subresource glClearBufferfi(GL_DEPTH_STENCIL, 0, value.depth, value.stencil); break; + default: + UNREACHABLE_MSG("Invalid surface type!"); } return true; @@ -146,24 +160,28 @@ bool TextureRuntime::BlitTextures(const OGLTexture& src_tex, Subresource src_sub }; // Sanity check; Can't blit a color texture to a depth buffer - ASSERT(src_subresource.aspect == dst_subresource.aspect); - switch (src_subresource.aspect) { - case Aspect::Color: + ASSERT(src_subresource.type == dst_subresource.type); + switch (src_subresource.type) { + case SurfaceType::Color: + case SurfaceType::Texture: + case SurfaceType::Fill: // Bind only color BindAttachment(GL_COLOR_ATTACHMENT0, src_tex.handle, dst_tex.handle); BindAttachment(GL_DEPTH_STENCIL_ATTACHMENT, 0, 0); break; - case Aspect::Depth: + case SurfaceType::Depth: // Bind only depth BindAttachment(GL_COLOR_ATTACHMENT0, 0, 0); BindAttachment(GL_DEPTH_ATTACHMENT, src_tex.handle, dst_tex.handle); BindAttachment(GL_STENCIL_ATTACHMENT, 0, 0); break; - case Aspect::DepthStencil: + case SurfaceType::DepthStencil: // Bind to combined depth + stencil BindAttachment(GL_COLOR_ATTACHMENT0, 0, 0); BindAttachment(GL_DEPTH_STENCIL_ATTACHMENT, src_tex.handle, dst_tex.handle); break; + default: + UNREACHABLE_MSG("Invalid surface type!"); } // TODO (wwylele): use GL_NEAREST for shadow map texture @@ -171,12 +189,13 @@ bool TextureRuntime::BlitTextures(const OGLTexture& src_tex, Subresource src_sub // doing linear intepolation componentwise would cause incorrect value. However, for a // well-programmed game this code path should be rarely executed for shadow map with // inconsistent scale. - const GLenum filter = src_subresource.aspect == Aspect::Color ? GL_LINEAR : GL_NEAREST; + const GLbitfield buffer_mask = MakeBufferMask(src_subresource.type); + const GLenum filter = buffer_mask == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST; const auto& src_rect = src_subresource.region; const auto& dst_rect = dst_subresource.region; glBlitFramebuffer(src_rect.left, src_rect.bottom, src_rect.right, src_rect.top, dst_rect.left, dst_rect.bottom, dst_rect.right, dst_rect.top, - ToBufferMask(src_subresource.aspect), filter); + buffer_mask, filter); return true; } diff --git a/src/video_core/rasterizer_cache/types.h b/src/video_core/rasterizer_cache/types.h index 8e0ad32ff..39610f3d3 100644 --- a/src/video_core/rasterizer_cache/types.h +++ b/src/video_core/rasterizer_cache/types.h @@ -3,18 +3,12 @@ // Refer to the license.txt file included. #pragma once -#include -#include -#include -#include "common/common_types.h" #include "common/math_util.h" #include "common/vector_math.h" +#include "video_core/rasterizer_cache/pixel_format.h" namespace OpenGL { -// Describes the type of data a texture holds -enum class Aspect { Color = 0, Depth = 1, DepthStencil = 2 }; - // A union for both color and depth/stencil clear values union ClearValue { Common::Vec4f color; @@ -27,7 +21,7 @@ union ClearValue { struct Subresource { auto operator<=>(const Subresource&) const = default; - Aspect aspect; + SurfaceType type; Common::Rectangle region; u32 level = 0; u32 layer = 0; diff --git a/src/video_core/rasterizer_cache/utils.cpp b/src/video_core/rasterizer_cache/utils.cpp index 4e4dc9031..a819100fd 100644 --- a/src/video_core/rasterizer_cache/utils.cpp +++ b/src/video_core/rasterizer_cache/utils.cpp @@ -4,6 +4,7 @@ #pragma once #include +#include "common/assert.h" #include "video_core/texture/texture_decode.h" #include "video_core/rasterizer_cache/morton_swizzle.h" #include "video_core/rasterizer_cache/surface_params.h" @@ -99,10 +100,12 @@ void UnswizzleTexture(const SurfaceParams& params, u32 load_start, u32 load_end, } } -ClearValue MakeClearValue(Aspect aspect, PixelFormat format, const u8* fill_data) { +ClearValue MakeClearValue(SurfaceType type, PixelFormat format, const u8* fill_data) { ClearValue result{}; - switch (aspect) { - case Aspect::Color: { + switch (type) { + case SurfaceType::Color: + case SurfaceType::Texture: + case SurfaceType::Fill: { Pica::Texture::TextureInfo tex_info{}; tex_info.format = static_cast(format); @@ -110,7 +113,7 @@ ClearValue MakeClearValue(Aspect aspect, PixelFormat format, const u8* fill_data result.color = color / 255.f; break; } - case Aspect::Depth: { + case SurfaceType::Depth: { u32 depth_uint = 0; if (format == PixelFormat::D16) { std::memcpy(&depth_uint, fill_data, 2); @@ -121,7 +124,7 @@ ClearValue MakeClearValue(Aspect aspect, PixelFormat format, const u8* fill_data } break; } - case Aspect::DepthStencil: { + case SurfaceType::DepthStencil: { u32 clear_value_uint; std::memcpy(&clear_value_uint, fill_data, sizeof(u32)); @@ -129,27 +132,11 @@ ClearValue MakeClearValue(Aspect aspect, PixelFormat format, const u8* fill_data result.stencil = (clear_value_uint >> 24); break; } + default: + UNREACHABLE_MSG("Invalid surface type!"); } return result; } -Aspect ToAspect(SurfaceType type) { - switch (type) { - case SurfaceType::Color: - case SurfaceType::Texture: - case SurfaceType::Fill: - return Aspect::Color; - case SurfaceType::Depth: - return Aspect::Depth; - case SurfaceType::DepthStencil: - return Aspect::DepthStencil; - default: - LOG_CRITICAL(Render_OpenGL, "Unknown SurfaceType {}", type); - UNREACHABLE(); - } - - return Aspect::Color; -} - } // namespace OpenGL diff --git a/src/video_core/rasterizer_cache/utils.h b/src/video_core/rasterizer_cache/utils.h index 7070586b0..79cd228be 100644 --- a/src/video_core/rasterizer_cache/utils.h +++ b/src/video_core/rasterizer_cache/utils.h @@ -56,9 +56,7 @@ void SwizzleTexture(const SurfaceParams& params, u32 flush_start, u32 flush_end, void UnswizzleTexture(const SurfaceParams& params, u32 load_start, u32 load_end, std::span source, std::span dest); -[[nodiscard]] ClearValue MakeClearValue(Aspect aspect, PixelFormat format, const u8* fill_data); - -[[nodiscard]] Aspect ToAspect(SurfaceType type); +[[nodiscard]] ClearValue MakeClearValue(SurfaceType type, PixelFormat format, const u8* fill_data); } // namespace OpenGL