diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 3cef900ee..397b546be 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -127,7 +127,7 @@ target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) create_target_directory_groups(video_core) -target_link_libraries(video_core PUBLIC citra_common core) +target_link_libraries(video_core PUBLIC citra_common citra_core) target_link_libraries(video_core PRIVATE glad tsl::robin_map json-headers dds-ktx nihstro-headers Boost::serialization) set_target_properties(video_core PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${ENABLE_LTO}) diff --git a/src/video_core/rasterizer_cache/surface_base.h b/src/video_core/rasterizer_cache/surface_base.h index 4f5c671ea..17781a73b 100644 --- a/src/video_core/rasterizer_cache/surface_base.h +++ b/src/video_core/rasterizer_cache/surface_base.h @@ -18,6 +18,7 @@ enum class SurfaceFlagBits : u32 { Picked = 1 << 1, ///< Surface has been picked when searching for a match. Tracked = 1 << 2, ///< Surface is part of a texture cube and should be tracked. Custom = 1 << 3, ///< Surface texture has been replaced with a custom texture. + ShadowMap = 1 << 4, ///< Surface is used during shadow rendering. }; DECLARE_ENUM_FLAG_OPERATORS(SurfaceFlagBits); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index c74c63bbe..6a796bcbc 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -510,6 +510,7 @@ void RasterizerOpenGL::SyncTextureUnits(const Framebuffer& framebuffer) { switch (texture.config.type.Value()) { case TextureType::Shadow2D: { Surface& surface = res_cache.GetTextureSurface(texture); + surface.flags |= VideoCore::SurfaceFlagBits::ShadowMap; state.image_shadow_texture_px = surface.Handle(); continue; } @@ -553,6 +554,7 @@ void RasterizerOpenGL::BindShadowCube(const Pica::TexturingRegs::FullTextureConf VideoCore::SurfaceId surface_id = res_cache.GetTextureSurface(info); Surface& surface = res_cache.GetSurface(surface_id); + surface.flags |= VideoCore::SurfaceFlagBits::ShadowMap; state.image_shadow_texture[binding] = surface.Handle(); } } diff --git a/src/video_core/renderer_opengl/gl_texture_runtime.cpp b/src/video_core/renderer_opengl/gl_texture_runtime.cpp index 6cefcd060..490e76e37 100644 --- a/src/video_core/renderer_opengl/gl_texture_runtime.cpp +++ b/src/video_core/renderer_opengl/gl_texture_runtime.cpp @@ -17,6 +17,7 @@ namespace { using VideoCore::MapType; using VideoCore::PixelFormat; +using VideoCore::SurfaceFlagBits; using VideoCore::SurfaceType; using VideoCore::TextureType; @@ -339,13 +340,12 @@ bool TextureRuntime::BlitTextures(Surface& source, Surface& dest, source.Attach(GL_READ_FRAMEBUFFER, blit.src_level, blit.src_layer); dest.Attach(GL_DRAW_FRAMEBUFFER, blit.dst_level, blit.dst_layer); - // TODO (wwylele): use GL_NEAREST for shadow map texture // Note: shadow map is treated as RGBA8 format in PICA, as well as in the rasterizer cache, but - // 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. + // doing linear intepolation componentwise would cause incorrect value. const GLbitfield buffer_mask = MakeBufferMask(source.type); - const GLenum filter = buffer_mask == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST; + const bool is_shadow_map = True(source.flags & SurfaceFlagBits::ShadowMap); + const GLenum filter = + buffer_mask == GL_COLOR_BUFFER_BIT && !is_shadow_map ? GL_LINEAR : GL_NEAREST; glBlitFramebuffer(blit.src_rect.left, blit.src_rect.bottom, blit.src_rect.right, blit.src_rect.top, blit.dst_rect.left, blit.dst_rect.bottom, blit.dst_rect.right, blit.dst_rect.top, buffer_mask, filter);