From 5213f702307e43520ad5f264e613acdfec597077 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Thu, 4 Mar 2021 14:12:25 -0500 Subject: texture_cache: Blacklist BGRA8 copies and views on OpenGL In order to force the BGRA8 conversion on Nvidia using OpenGL, we need to forbid texture copies and views with other formats. This commit also adds a boolean relating to this, as this needs to be done only for the OpenGL api, Vulkan must remain unchanged. --- src/video_core/compatible_formats.cpp | 49 +++++++++++++++++++---- src/video_core/compatible_formats.h | 5 ++- src/video_core/renderer_opengl/gl_texture_cache.h | 5 +++ src/video_core/renderer_vulkan/vk_texture_cache.h | 5 +++ src/video_core/texture_cache/image_base.cpp | 5 ++- src/video_core/texture_cache/image_view_base.cpp | 2 +- src/video_core/texture_cache/texture_cache.h | 15 ++++--- src/video_core/texture_cache/util.cpp | 13 +++--- src/video_core/texture_cache/util.h | 9 +++-- 9 files changed, 80 insertions(+), 28 deletions(-) diff --git a/src/video_core/compatible_formats.cpp b/src/video_core/compatible_formats.cpp index acf2668dc..8317d0636 100644 --- a/src/video_core/compatible_formats.cpp +++ b/src/video_core/compatible_formats.cpp @@ -48,6 +48,15 @@ constexpr std::array VIEW_CLASS_32_BITS{ PixelFormat::A2B10G10R10_UINT, }; +constexpr std::array VIEW_CLASS_32_BITS_NO_BGR{ + PixelFormat::R16G16_FLOAT, PixelFormat::B10G11R11_FLOAT, PixelFormat::R32_FLOAT, + PixelFormat::A2B10G10R10_UNORM, PixelFormat::R16G16_UINT, PixelFormat::R32_UINT, + PixelFormat::R16G16_SINT, PixelFormat::R32_SINT, PixelFormat::A8B8G8R8_UNORM, + PixelFormat::R16G16_UNORM, PixelFormat::A8B8G8R8_SNORM, PixelFormat::R16G16_SNORM, + PixelFormat::A8B8G8R8_SRGB, PixelFormat::E5B9G9R9_FLOAT, PixelFormat::A8B8G8R8_UINT, + PixelFormat::A8B8G8R8_SINT, PixelFormat::A2B10G10R10_UINT, +}; + // TODO: How should we handle 24 bits? constexpr std::array VIEW_CLASS_16_BITS{ @@ -205,7 +214,6 @@ constexpr Table MakeViewTable() { EnableRange(view, VIEW_CLASS_128_BITS); EnableRange(view, VIEW_CLASS_96_BITS); EnableRange(view, VIEW_CLASS_64_BITS); - EnableRange(view, VIEW_CLASS_32_BITS); EnableRange(view, VIEW_CLASS_16_BITS); EnableRange(view, VIEW_CLASS_8_BITS); EnableRange(view, VIEW_CLASS_RGTC1_RED); @@ -231,20 +239,47 @@ constexpr Table MakeCopyTable() { EnableRange(copy, COPY_CLASS_64_BITS); return copy; } + +constexpr Table MakeNativeBgrViewTable() { + Table copy = MakeViewTable(); + EnableRange(copy, VIEW_CLASS_32_BITS); + return copy; +} + +constexpr Table MakeNonNativeBgrViewTable() { + Table copy = MakeViewTable(); + EnableRange(copy, VIEW_CLASS_32_BITS_NO_BGR); + return copy; +} + +constexpr Table MakeNativeBgrCopyTable() { + Table copy = MakeCopyTable(); + EnableRange(copy, VIEW_CLASS_32_BITS); + return copy; +} + +constexpr Table MakeNonNativeBgrCopyTable() { + Table copy = MakeCopyTable(); + EnableRange(copy, VIEW_CLASS_32_BITS); + return copy; +} } // Anonymous namespace -bool IsViewCompatible(PixelFormat format_a, PixelFormat format_b, bool broken_views) { +bool IsViewCompatible(PixelFormat format_a, PixelFormat format_b, bool broken_views, + bool native_bgr) { if (broken_views) { // If format views are broken, only accept formats that are identical. return format_a == format_b; } - static constexpr Table TABLE = MakeViewTable(); - return IsSupported(TABLE, format_a, format_b); + static constexpr Table BGR_TABLE = MakeNativeBgrViewTable(); + static constexpr Table NO_BGR_TABLE = MakeNonNativeBgrViewTable(); + return IsSupported(native_bgr ? BGR_TABLE : NO_BGR_TABLE, format_a, format_b); } -bool IsCopyCompatible(PixelFormat format_a, PixelFormat format_b) { - static constexpr Table TABLE = MakeCopyTable(); - return IsSupported(TABLE, format_a, format_b); +bool IsCopyCompatible(PixelFormat format_a, PixelFormat format_b, bool native_bgr) { + static constexpr Table BGR_TABLE = MakeNativeBgrCopyTable(); + static constexpr Table NO_BGR_TABLE = MakeNonNativeBgrCopyTable(); + return IsSupported(native_bgr ? BGR_TABLE : NO_BGR_TABLE, format_a, format_b); } } // namespace VideoCore::Surface diff --git a/src/video_core/compatible_formats.h b/src/video_core/compatible_formats.h index 9a0522988..55745e042 100644 --- a/src/video_core/compatible_formats.h +++ b/src/video_core/compatible_formats.h @@ -8,8 +8,9 @@ namespace VideoCore::Surface { -bool IsViewCompatible(PixelFormat format_a, PixelFormat format_b, bool broken_views); +bool IsViewCompatible(PixelFormat format_a, PixelFormat format_b, bool broken_views, + bool native_bgr); -bool IsCopyCompatible(PixelFormat format_a, PixelFormat format_b); +bool IsCopyCompatible(PixelFormat format_a, PixelFormat format_b, bool native_bgr); } // namespace VideoCore::Surface diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index a6172f009..3fbaa102f 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h @@ -86,6 +86,11 @@ public: FormatProperties FormatInfo(VideoCommon::ImageType type, GLenum internal_format) const; + bool HasNativeBgr() const noexcept { + // OpenGL does not have native support for the BGR internal format + return false; + } + bool HasBrokenTextureViewFormats() const noexcept { return has_broken_texture_view_formats; } diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index b08c23459..3aee27ce0 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -93,6 +93,11 @@ struct TextureCacheRuntime { // No known Vulkan driver has broken image views return false; } + + bool HasNativeBgr() const noexcept { + // All known Vulkan drivers can natively handle BGR textures + return true; + } }; class Image : public VideoCommon::ImageBase { diff --git a/src/video_core/texture_cache/image_base.cpp b/src/video_core/texture_cache/image_base.cpp index 959b3f115..9914926b3 100644 --- a/src/video_core/texture_cache/image_base.cpp +++ b/src/video_core/texture_cache/image_base.cpp @@ -120,9 +120,10 @@ void AddImageAlias(ImageBase& lhs, ImageBase& rhs, ImageId lhs_id, ImageId rhs_i if (lhs.info.type == ImageType::Linear) { base = SubresourceBase{.level = 0, .layer = 0}; } else { - // We are passing relaxed formats as an option, having broken views or not won't matter + // We are passing relaxed formats as an option, having broken views/bgr or not won't matter static constexpr bool broken_views = false; - base = FindSubresource(rhs.info, lhs, rhs.gpu_addr, OPTIONS, broken_views); + static constexpr bool native_bgr = true; + base = FindSubresource(rhs.info, lhs, rhs.gpu_addr, OPTIONS, broken_views, native_bgr); } if (!base) { LOG_ERROR(HW_GPU, "Image alias should have been flipped"); diff --git a/src/video_core/texture_cache/image_view_base.cpp b/src/video_core/texture_cache/image_view_base.cpp index 18f72e508..f89a40b4c 100644 --- a/src/video_core/texture_cache/image_view_base.cpp +++ b/src/video_core/texture_cache/image_view_base.cpp @@ -24,7 +24,7 @@ ImageViewBase::ImageViewBase(const ImageViewInfo& info, const ImageInfo& image_i .height = std::max(image_info.size.height >> range.base.level, 1u), .depth = std::max(image_info.size.depth >> range.base.level, 1u), } { - ASSERT_MSG(VideoCore::Surface::IsViewCompatible(image_info.format, info.format, false), + ASSERT_MSG(VideoCore::Surface::IsViewCompatible(image_info.format, info.format, false, true), "Image view format {} is incompatible with image format {}", info.format, image_info.format); const bool is_async = Settings::values.use_asynchronous_gpu_emulation.GetValue(); diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index b1da69971..98e33c3a0 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -876,6 +876,7 @@ ImageId TextureCache
::FindImage(const ImageInfo& info, GPUVAddr gpu_addr, return ImageId{}; } const bool broken_views = runtime.HasBrokenTextureViewFormats(); + const bool native_bgr = runtime.HasNativeBgr(); ImageId image_id; const auto lambda = [&](ImageId existing_image_id, ImageBase& existing_image) { if (info.type == ImageType::Linear || existing_image.info.type == ImageType::Linear) { @@ -885,11 +886,12 @@ ImageId TextureCache
::FindImage(const ImageInfo& info, GPUVAddr gpu_addr, if (existing_image.gpu_addr == gpu_addr && existing.type == info.type && existing.pitch == info.pitch && IsPitchLinearSameSize(existing, info, strict_size) && - IsViewCompatible(existing.format, info.format, broken_views)) { + IsViewCompatible(existing.format, info.format, broken_views, native_bgr)) { image_id = existing_image_id; return true; } - } else if (IsSubresource(info, existing_image, gpu_addr, options, broken_views)) { + } else if (IsSubresource(info, existing_image, gpu_addr, options, broken_views, + native_bgr)) { image_id = existing_image_id; return true; } @@ -920,6 +922,7 @@ ImageId TextureCache
::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA
ImageInfo new_info = info;
const size_t size_bytes = CalculateGuestSizeInBytes(new_info);
const bool broken_views = runtime.HasBrokenTextureViewFormats();
+ const bool native_bgr = runtime.HasNativeBgr();
std::vector ::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA
return;
}
static constexpr bool strict_size = true;
- const std::optional ::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA
}
static constexpr auto options = RelaxedOptions::Size | RelaxedOptions::Format;
const ImageBase new_image_base(new_info, gpu_addr, cpu_addr);
- if (IsSubresource(new_info, overlap, gpu_addr, options, broken_views)) {
+ if (IsSubresource(new_info, overlap, gpu_addr, options, broken_views, native_bgr)) {
left_aliased_ids.push_back(overlap_id);
} else if (IsSubresource(overlap.info, new_image_base, overlap.gpu_addr, options,
- broken_views)) {
+ broken_views, native_bgr)) {
right_aliased_ids.push_back(overlap_id);
}
});
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp
index a0bc1f7b6..2c42d1449 100644
--- a/src/video_core/texture_cache/util.cpp
+++ b/src/video_core/texture_cache/util.cpp
@@ -1035,13 +1035,13 @@ bool IsPitchLinearSameSize(const ImageInfo& lhs, const ImageInfo& rhs, bool stri
std::optional