early-access version 3682

This commit is contained in:
pineappleEA 2023-06-16 06:24:57 +02:00
parent 22fb9ebe53
commit 915fe36508
22 changed files with 105 additions and 222 deletions

View file

@ -1,7 +1,7 @@
yuzu emulator early access yuzu emulator early access
============= =============
This is the source code for early-access 3680. This is the source code for early-access 3682.
## Legal Notice ## Legal Notice

View file

@ -245,7 +245,6 @@ void RestoreGlobalState(bool is_powered_on) {
values.bg_blue.SetGlobal(true); values.bg_blue.SetGlobal(true);
values.enable_compute_pipelines.SetGlobal(true); values.enable_compute_pipelines.SetGlobal(true);
values.use_video_framerate.SetGlobal(true); values.use_video_framerate.SetGlobal(true);
values.use_aggressive_anisotropic_filtering.SetGlobal(true);
// System // System
values.language_index.SetGlobal(true); values.language_index.SetGlobal(true);

View file

@ -483,8 +483,7 @@ struct Values {
AstcRecompression::Uncompressed, AstcRecompression::Uncompressed, AstcRecompression::Bc3, AstcRecompression::Uncompressed, AstcRecompression::Uncompressed, AstcRecompression::Bc3,
"astc_recompression"}; "astc_recompression"};
SwitchableSetting<bool> use_video_framerate{false, "use_video_framerate"}; SwitchableSetting<bool> use_video_framerate{false, "use_video_framerate"};
SwitchableSetting<bool> use_aggressive_anisotropic_filtering{ SwitchableSetting<bool> barrier_feedback_loops{true, "barrier_feedback_loops"};
false, "use_aggressive_anisotropic_filtering"};
SwitchableSetting<u8> bg_red{0, "bg_red"}; SwitchableSetting<u8> bg_red{0, "bg_red"};
SwitchableSetting<u8> bg_green{0, "bg_green"}; SwitchableSetting<u8> bg_green{0, "bg_green"};

View file

@ -275,9 +275,9 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c
template <typename Spec> template <typename Spec>
void GraphicsPipeline::ConfigureImpl(bool is_indexed) { void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
std::array<VideoCommon::ImageViewInOut, MAX_TEXTURES + MAX_IMAGES> views; std::array<VideoCommon::ImageViewInOut, MAX_TEXTURES + MAX_IMAGES> views;
std::array<const Sampler*, MAX_TEXTURES> samplers; std::array<GLuint, MAX_TEXTURES> samplers;
size_t views_index{}; size_t views_index{};
size_t samplers_index{}; GLsizei sampler_binding{};
texture_cache.SynchronizeGraphicsDescriptors(); texture_cache.SynchronizeGraphicsDescriptors();
@ -337,6 +337,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
for (u32 index = 0; index < desc.count; ++index) { for (u32 index = 0; index < desc.count; ++index) {
const auto handle{read_handle(desc, index)}; const auto handle{read_handle(desc, index)};
views[views_index++] = {handle.first}; views[views_index++] = {handle.first};
samplers[sampler_binding++] = 0;
} }
} }
} }
@ -351,7 +352,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
views[views_index++] = {handle.first}; views[views_index++] = {handle.first};
Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.second)}; Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.second)};
samplers[samplers_index++] = sampler; samplers[sampler_binding++] = sampler->Handle();
} }
} }
if constexpr (Spec::has_images) { if constexpr (Spec::has_images) {
@ -444,13 +445,10 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
program_manager.BindSourcePrograms(source_programs); program_manager.BindSourcePrograms(source_programs);
} }
const VideoCommon::ImageViewInOut* views_it{views.data()}; const VideoCommon::ImageViewInOut* views_it{views.data()};
const Sampler** samplers_it{samplers.data()};
GLsizei texture_binding = 0; GLsizei texture_binding = 0;
GLsizei image_binding = 0; GLsizei image_binding = 0;
GLsizei sampler_binding{};
std::array<GLuint, MAX_TEXTURES> textures; std::array<GLuint, MAX_TEXTURES> textures;
std::array<GLuint, MAX_IMAGES> images; std::array<GLuint, MAX_IMAGES> images;
std::array<GLuint, MAX_TEXTURES> gl_samplers;
const auto prepare_stage{[&](size_t stage) { const auto prepare_stage{[&](size_t stage) {
buffer_cache.runtime.SetImagePointers(&textures[texture_binding], &images[image_binding]); buffer_cache.runtime.SetImagePointers(&textures[texture_binding], &images[image_binding]);
buffer_cache.BindHostStageBuffers(stage); buffer_cache.BindHostStageBuffers(stage);
@ -467,13 +465,6 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
u32 stage_image_binding{}; u32 stage_image_binding{};
const auto& info{stage_infos[stage]}; const auto& info{stage_infos[stage]};
if constexpr (Spec::has_texture_buffers) {
for (const auto& desc : info.texture_buffer_descriptors) {
for (u32 index = 0; index < desc.count; ++index) {
gl_samplers[sampler_binding++] = 0;
}
}
}
for (const auto& desc : info.texture_descriptors) { for (const auto& desc : info.texture_descriptors) {
for (u32 index = 0; index < desc.count; ++index) { for (u32 index = 0; index < desc.count; ++index) {
ImageView& image_view{texture_cache.GetImageView((views_it++)->id)}; ImageView& image_view{texture_cache.GetImageView((views_it++)->id)};
@ -483,12 +474,6 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
} }
++texture_binding; ++texture_binding;
++stage_texture_binding; ++stage_texture_binding;
const Sampler& sampler{**(samplers_it++)};
const bool use_fallback_sampler{sampler.HasAddedAnisotropy() &&
!image_view.SupportsAnisotropy()};
gl_samplers[sampler_binding++] =
use_fallback_sampler ? sampler.HandleWithDefaultAnisotropy() : sampler.Handle();
} }
} }
for (const auto& desc : info.image_descriptors) { for (const auto& desc : info.image_descriptors) {
@ -549,7 +534,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
if (texture_binding != 0) { if (texture_binding != 0) {
ASSERT(texture_binding == sampler_binding); ASSERT(texture_binding == sampler_binding);
glBindTextures(0, texture_binding, textures.data()); glBindTextures(0, texture_binding, textures.data());
glBindSamplers(0, sampler_binding, gl_samplers.data()); glBindSamplers(0, sampler_binding, samplers.data());
} }
if (image_binding != 0) { if (image_binding != 0) {
glBindImageTextures(0, image_binding, images.data()); glBindImageTextures(0, image_binding, images.data());

View file

@ -1268,48 +1268,36 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const TSCEntry& config) {
UNIMPLEMENTED_IF(config.cubemap_anisotropy != 1); UNIMPLEMENTED_IF(config.cubemap_anisotropy != 1);
const f32 max_anisotropy = std::clamp(config.MaxAnisotropy(), 1.0f, 16.0f); sampler.Create();
const GLuint handle = sampler.handle;
glSamplerParameteri(handle, GL_TEXTURE_WRAP_S, MaxwellToGL::WrapMode(config.wrap_u));
glSamplerParameteri(handle, GL_TEXTURE_WRAP_T, MaxwellToGL::WrapMode(config.wrap_v));
glSamplerParameteri(handle, GL_TEXTURE_WRAP_R, MaxwellToGL::WrapMode(config.wrap_p));
glSamplerParameteri(handle, GL_TEXTURE_COMPARE_MODE, compare_mode);
glSamplerParameteri(handle, GL_TEXTURE_COMPARE_FUNC, compare_func);
glSamplerParameteri(handle, GL_TEXTURE_MAG_FILTER, mag);
glSamplerParameteri(handle, GL_TEXTURE_MIN_FILTER, min);
glSamplerParameterf(handle, GL_TEXTURE_LOD_BIAS, config.LodBias());
glSamplerParameterf(handle, GL_TEXTURE_MIN_LOD, config.MinLod());
glSamplerParameterf(handle, GL_TEXTURE_MAX_LOD, config.MaxLod());
glSamplerParameterfv(handle, GL_TEXTURE_BORDER_COLOR, config.BorderColor().data());
const auto create_sampler = [&](const f32 anisotropy) { if (GLAD_GL_ARB_texture_filter_anisotropic || GLAD_GL_EXT_texture_filter_anisotropic) {
OGLSampler new_sampler; const f32 max_anisotropy = std::clamp(config.MaxAnisotropy(), 1.0f, 16.0f);
new_sampler.Create(); glSamplerParameterf(handle, GL_TEXTURE_MAX_ANISOTROPY, max_anisotropy);
const GLuint handle = new_sampler.handle; } else {
glSamplerParameteri(handle, GL_TEXTURE_WRAP_S, MaxwellToGL::WrapMode(config.wrap_u)); LOG_WARNING(Render_OpenGL, "GL_ARB_texture_filter_anisotropic is required");
glSamplerParameteri(handle, GL_TEXTURE_WRAP_T, MaxwellToGL::WrapMode(config.wrap_v)); }
glSamplerParameteri(handle, GL_TEXTURE_WRAP_R, MaxwellToGL::WrapMode(config.wrap_p)); if (GLAD_GL_ARB_texture_filter_minmax || GLAD_GL_EXT_texture_filter_minmax) {
glSamplerParameteri(handle, GL_TEXTURE_COMPARE_MODE, compare_mode); glSamplerParameteri(handle, GL_TEXTURE_REDUCTION_MODE_ARB, reduction_filter);
glSamplerParameteri(handle, GL_TEXTURE_COMPARE_FUNC, compare_func); } else if (reduction_filter != GL_WEIGHTED_AVERAGE_ARB) {
glSamplerParameteri(handle, GL_TEXTURE_MAG_FILTER, mag); LOG_WARNING(Render_OpenGL, "GL_ARB_texture_filter_minmax is required");
glSamplerParameteri(handle, GL_TEXTURE_MIN_FILTER, min); }
glSamplerParameterf(handle, GL_TEXTURE_LOD_BIAS, config.LodBias()); if (GLAD_GL_ARB_seamless_cubemap_per_texture || GLAD_GL_AMD_seamless_cubemap_per_texture) {
glSamplerParameterf(handle, GL_TEXTURE_MIN_LOD, config.MinLod()); glSamplerParameteri(handle, GL_TEXTURE_CUBE_MAP_SEAMLESS, seamless);
glSamplerParameterf(handle, GL_TEXTURE_MAX_LOD, config.MaxLod()); } else if (seamless == GL_FALSE) {
glSamplerParameterfv(handle, GL_TEXTURE_BORDER_COLOR, config.BorderColor().data()); // We default to false because it's more common
LOG_WARNING(Render_OpenGL, "GL_ARB_seamless_cubemap_per_texture is required");
if (GLAD_GL_ARB_texture_filter_anisotropic || GLAD_GL_EXT_texture_filter_anisotropic) {
glSamplerParameterf(handle, GL_TEXTURE_MAX_ANISOTROPY, anisotropy);
} else {
LOG_WARNING(Render_OpenGL, "GL_ARB_texture_filter_anisotropic is required");
}
if (GLAD_GL_ARB_texture_filter_minmax || GLAD_GL_EXT_texture_filter_minmax) {
glSamplerParameteri(handle, GL_TEXTURE_REDUCTION_MODE_ARB, reduction_filter);
} else if (reduction_filter != GL_WEIGHTED_AVERAGE_ARB) {
LOG_WARNING(Render_OpenGL, "GL_ARB_texture_filter_minmax is required");
}
if (GLAD_GL_ARB_seamless_cubemap_per_texture || GLAD_GL_AMD_seamless_cubemap_per_texture) {
glSamplerParameteri(handle, GL_TEXTURE_CUBE_MAP_SEAMLESS, seamless);
} else if (seamless == GL_FALSE) {
// We default to false because it's more common
LOG_WARNING(Render_OpenGL, "GL_ARB_seamless_cubemap_per_texture is required");
}
return new_sampler;
};
sampler = create_sampler(max_anisotropy);
const f32 max_anisotropy_default = static_cast<f32>(1U << config.max_anisotropy);
if (max_anisotropy > max_anisotropy_default) {
sampler_default_anisotropy = create_sampler(max_anisotropy_default);
} }
} }

View file

@ -309,21 +309,12 @@ class Sampler {
public: public:
explicit Sampler(TextureCacheRuntime&, const Tegra::Texture::TSCEntry&); explicit Sampler(TextureCacheRuntime&, const Tegra::Texture::TSCEntry&);
[[nodiscard]] GLuint Handle() const noexcept { GLuint Handle() const noexcept {
return sampler.handle; return sampler.handle;
} }
[[nodiscard]] GLuint HandleWithDefaultAnisotropy() const noexcept {
return sampler_default_anisotropy.handle;
}
[[nodiscard]] bool HasAddedAnisotropy() const noexcept {
return static_cast<bool>(sampler_default_anisotropy.handle);
}
private: private:
OGLSampler sampler; OGLSampler sampler;
OGLSampler sampler_default_anisotropy;
}; };
class Framebuffer { class Framebuffer {

View file

@ -178,7 +178,7 @@ public:
inline void PushImageDescriptors(TextureCache& texture_cache, inline void PushImageDescriptors(TextureCache& texture_cache,
GuestDescriptorQueue& guest_descriptor_queue, GuestDescriptorQueue& guest_descriptor_queue,
const Shader::Info& info, RescalingPushConstant& rescaling, const Shader::Info& info, RescalingPushConstant& rescaling,
const Sampler**& samplers, const VkSampler*& samplers,
const VideoCommon::ImageViewInOut*& views) { const VideoCommon::ImageViewInOut*& views) {
const u32 num_texture_buffers = Shader::NumDescriptors(info.texture_buffer_descriptors); const u32 num_texture_buffers = Shader::NumDescriptors(info.texture_buffer_descriptors);
const u32 num_image_buffers = Shader::NumDescriptors(info.image_buffer_descriptors); const u32 num_image_buffers = Shader::NumDescriptors(info.image_buffer_descriptors);
@ -187,14 +187,10 @@ inline void PushImageDescriptors(TextureCache& texture_cache,
for (const auto& desc : info.texture_descriptors) { for (const auto& desc : info.texture_descriptors) {
for (u32 index = 0; index < desc.count; ++index) { for (u32 index = 0; index < desc.count; ++index) {
const VideoCommon::ImageViewId image_view_id{(views++)->id}; const VideoCommon::ImageViewId image_view_id{(views++)->id};
const VkSampler sampler{*(samplers++)};
ImageView& image_view{texture_cache.GetImageView(image_view_id)}; ImageView& image_view{texture_cache.GetImageView(image_view_id)};
const VkImageView vk_image_view{image_view.Handle(desc.type)}; const VkImageView vk_image_view{image_view.Handle(desc.type)};
const Sampler& sampler{**(samplers++)}; guest_descriptor_queue.AddSampledImage(vk_image_view, sampler);
const bool use_fallback_sampler{sampler.HasAddedAnisotropy() &&
!image_view.SupportsAnisotropy()};
const VkSampler vk_sampler{use_fallback_sampler ? sampler.HandleWithDefaultAnisotropy()
: sampler.Handle()};
guest_descriptor_queue.AddSampledImage(vk_image_view, vk_sampler);
rescaling.PushTexture(texture_cache.IsRescaling(image_view)); rescaling.PushTexture(texture_cache.IsRescaling(image_view));
} }
} }

View file

@ -115,7 +115,7 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
static constexpr size_t max_elements = 64; static constexpr size_t max_elements = 64;
boost::container::static_vector<VideoCommon::ImageViewInOut, max_elements> views; boost::container::static_vector<VideoCommon::ImageViewInOut, max_elements> views;
boost::container::static_vector<const Sampler*, max_elements> samplers; boost::container::static_vector<VkSampler, max_elements> samplers;
const auto& qmd{kepler_compute.launch_description}; const auto& qmd{kepler_compute.launch_description};
const auto& cbufs{qmd.const_buffer_config}; const auto& cbufs{qmd.const_buffer_config};
@ -161,7 +161,7 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
views.push_back({handle.first}); views.push_back({handle.first});
Sampler* const sampler = texture_cache.GetComputeSampler(handle.second); Sampler* const sampler = texture_cache.GetComputeSampler(handle.second);
samplers.push_back(sampler); samplers.push_back(sampler->Handle());
} }
} }
for (const auto& desc : info.image_descriptors) { for (const auto& desc : info.image_descriptors) {
@ -192,7 +192,7 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
buffer_cache.BindHostComputeBuffers(); buffer_cache.BindHostComputeBuffers();
RescalingPushConstant rescaling; RescalingPushConstant rescaling;
const Sampler** samplers_it{samplers.data()}; const VkSampler* samplers_it{samplers.data()};
const VideoCommon::ImageViewInOut* views_it{views.data()}; const VideoCommon::ImageViewInOut* views_it{views.data()};
PushImageDescriptors(texture_cache, guest_descriptor_queue, info, rescaling, samplers_it, PushImageDescriptors(texture_cache, guest_descriptor_queue, info, rescaling, samplers_it,
views_it); views_it);

View file

@ -298,7 +298,7 @@ void GraphicsPipeline::AddTransition(GraphicsPipeline* transition) {
template <typename Spec> template <typename Spec>
void GraphicsPipeline::ConfigureImpl(bool is_indexed) { void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
std::array<VideoCommon::ImageViewInOut, MAX_IMAGE_ELEMENTS> views; std::array<VideoCommon::ImageViewInOut, MAX_IMAGE_ELEMENTS> views;
std::array<const Sampler*, MAX_IMAGE_ELEMENTS> samplers; std::array<VkSampler, MAX_IMAGE_ELEMENTS> samplers;
size_t sampler_index{}; size_t sampler_index{};
size_t view_index{}; size_t view_index{};
@ -368,7 +368,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
views[view_index++] = {handle.first}; views[view_index++] = {handle.first};
Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.second)}; Sampler* const sampler{texture_cache.GetGraphicsSampler(handle.second)};
samplers[sampler_index++] = sampler; samplers[sampler_index++] = sampler->Handle();
} }
} }
if constexpr (Spec::has_images) { if constexpr (Spec::has_images) {
@ -453,7 +453,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
RescalingPushConstant rescaling; RescalingPushConstant rescaling;
RenderAreaPushConstant render_area; RenderAreaPushConstant render_area;
const Sampler** samplers_it{samplers.data()}; const VkSampler* samplers_it{samplers.data()};
const VideoCommon::ImageViewInOut* views_it{views.data()}; const VideoCommon::ImageViewInOut* views_it{views.data()};
const auto prepare_stage{[&](size_t stage) LAMBDA_FORCEINLINE { const auto prepare_stage{[&](size_t stage) LAMBDA_FORCEINLINE {
buffer_cache.BindHostStageBuffers(stage); buffer_cache.BindHostStageBuffers(stage);

View file

@ -1803,36 +1803,27 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& t
// Some games have samplers with garbage. Sanitize them here. // Some games have samplers with garbage. Sanitize them here.
const f32 max_anisotropy = std::clamp(tsc.MaxAnisotropy(), 1.0f, 16.0f); const f32 max_anisotropy = std::clamp(tsc.MaxAnisotropy(), 1.0f, 16.0f);
const auto create_sampler = [&](const f32 anisotropy) { sampler = device.GetLogical().CreateSampler(VkSamplerCreateInfo{
return device.GetLogical().CreateSampler(VkSamplerCreateInfo{ .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, .pNext = pnext,
.pNext = pnext, .flags = 0,
.flags = 0, .magFilter = MaxwellToVK::Sampler::Filter(tsc.mag_filter),
.magFilter = MaxwellToVK::Sampler::Filter(tsc.mag_filter), .minFilter = MaxwellToVK::Sampler::Filter(tsc.min_filter),
.minFilter = MaxwellToVK::Sampler::Filter(tsc.min_filter), .mipmapMode = MaxwellToVK::Sampler::MipmapMode(tsc.mipmap_filter),
.mipmapMode = MaxwellToVK::Sampler::MipmapMode(tsc.mipmap_filter), .addressModeU = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_u, tsc.mag_filter),
.addressModeU = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_u, tsc.mag_filter), .addressModeV = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_v, tsc.mag_filter),
.addressModeV = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_v, tsc.mag_filter), .addressModeW = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_p, tsc.mag_filter),
.addressModeW = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_p, tsc.mag_filter), .mipLodBias = tsc.LodBias(),
.mipLodBias = tsc.LodBias(), .anisotropyEnable = static_cast<VkBool32>(max_anisotropy > 1.0f ? VK_TRUE : VK_FALSE),
.anisotropyEnable = static_cast<VkBool32>(anisotropy > 1.0f ? VK_TRUE : VK_FALSE), .maxAnisotropy = max_anisotropy,
.maxAnisotropy = anisotropy, .compareEnable = tsc.depth_compare_enabled,
.compareEnable = tsc.depth_compare_enabled, .compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func),
.compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func), .minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.MinLod(),
.minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.MinLod(), .maxLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.25f : tsc.MaxLod(),
.maxLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.25f : tsc.MaxLod(), .borderColor =
.borderColor = arbitrary_borders ? VK_BORDER_COLOR_FLOAT_CUSTOM_EXT : ConvertBorderColor(color),
arbitrary_borders ? VK_BORDER_COLOR_FLOAT_CUSTOM_EXT : ConvertBorderColor(color), .unnormalizedCoordinates = VK_FALSE,
.unnormalizedCoordinates = VK_FALSE, });
});
};
sampler = create_sampler(max_anisotropy);
const f32 max_anisotropy_default = static_cast<f32>(1U << tsc.max_anisotropy);
if (max_anisotropy > max_anisotropy_default) {
sampler_default_anisotropy = create_sampler(max_anisotropy_default);
}
} }
Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM_RT> color_buffers, Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM_RT> color_buffers,

View file

@ -279,17 +279,8 @@ public:
return *sampler; return *sampler;
} }
[[nodiscard]] VkSampler HandleWithDefaultAnisotropy() const noexcept {
return *sampler_default_anisotropy;
}
[[nodiscard]] bool HasAddedAnisotropy() const noexcept {
return static_cast<bool>(sampler_default_anisotropy);
}
private: private:
vk::Sampler sampler; vk::Sampler sampler;
vk::Sampler sampler_default_anisotropy;
}; };
class Framebuffer { class Framebuffer {

View file

@ -45,52 +45,4 @@ ImageViewBase::ImageViewBase(const ImageInfo& info, const ImageViewInfo& view_in
ImageViewBase::ImageViewBase(const NullImageViewParams&) : image_id{NULL_IMAGE_ID} {} ImageViewBase::ImageViewBase(const NullImageViewParams&) : image_id{NULL_IMAGE_ID} {}
bool ImageViewBase::SupportsAnisotropy() const noexcept {
using namespace VideoCommon;
switch (format) {
case PixelFormat::R8_UNORM:
case PixelFormat::R8_SNORM:
case PixelFormat::R8_SINT:
case PixelFormat::R8_UINT:
case PixelFormat::BC4_UNORM:
case PixelFormat::BC4_SNORM:
case PixelFormat::BC5_UNORM:
case PixelFormat::BC5_SNORM:
case PixelFormat::R32G32_FLOAT:
case PixelFormat::R32G32_SINT:
case PixelFormat::R32_FLOAT:
case PixelFormat::R16_FLOAT:
case PixelFormat::R16_UNORM:
case PixelFormat::R16_SNORM:
case PixelFormat::R16_UINT:
case PixelFormat::R16_SINT:
case PixelFormat::R16G16_UNORM:
case PixelFormat::R16G16_FLOAT:
case PixelFormat::R16G16_UINT:
case PixelFormat::R16G16_SINT:
case PixelFormat::R16G16_SNORM:
case PixelFormat::R8G8_UNORM:
case PixelFormat::R8G8_SNORM:
case PixelFormat::R8G8_SINT:
case PixelFormat::R8G8_UINT:
case PixelFormat::R32G32_UINT:
case PixelFormat::R32_UINT:
case PixelFormat::R32_SINT:
case PixelFormat::G4R4_UNORM:
// Depth formats
case PixelFormat::D32_FLOAT:
case PixelFormat::D16_UNORM:
// Stencil formats
case PixelFormat::S8_UINT:
// DepthStencil formats
case PixelFormat::D24_UNORM_S8_UINT:
case PixelFormat::S8_UINT_D24_UNORM:
case PixelFormat::D32_FLOAT_S8_UINT:
return false;
default:
break;
}
return range.extent.levels > 1;
}
} // namespace VideoCommon } // namespace VideoCommon

View file

@ -33,8 +33,6 @@ struct ImageViewBase {
return type == ImageViewType::Buffer; return type == ImageViewType::Buffer;
} }
[[nodiscard]] bool SupportsAnisotropy() const noexcept;
ImageId image_id{}; ImageId image_id{};
GPUVAddr gpu_addr = 0; GPUVAddr gpu_addr = 0;
PixelFormat format{}; PixelFormat format{};

View file

@ -186,6 +186,10 @@ void TextureCache<P>::FillComputeImageViews(std::span<ImageViewInOut> views) {
template <class P> template <class P>
void TextureCache<P>::CheckFeedbackLoop(std::span<const ImageViewInOut> views) { void TextureCache<P>::CheckFeedbackLoop(std::span<const ImageViewInOut> views) {
if (!Settings::values.barrier_feedback_loops.GetValue()) {
return;
}
const bool requires_barrier = [&] { const bool requires_barrier = [&] {
for (const auto& view : views) { for (const auto& view : views) {
if (!view.id) { if (!view.id) {

View file

@ -62,14 +62,7 @@ std::array<float, 4> TSCEntry::BorderColor() const noexcept {
} }
float TSCEntry::MaxAnisotropy() const noexcept { float TSCEntry::MaxAnisotropy() const noexcept {
const bool is_suitable_mipmap_filter = Settings::values.use_aggressive_anisotropic_filtering if (max_anisotropy == 0 && mipmap_filter != TextureMipmapFilter::Linear) {
? mipmap_filter != TextureMipmapFilter::None
: mipmap_filter == TextureMipmapFilter::Linear;
const bool has_regular_lods = min_lod_clamp == 0 && max_lod_clamp >= 256;
const bool is_bilinear_filter = min_filter == TextureFilter::Linear &&
reduction_filter == SamplerReduction::WeightedAverage;
if (max_anisotropy == 0 && (depth_compare_enabled || !has_regular_lods || !is_bilinear_filter ||
!is_suitable_mipmap_filter)) {
return 1.0f; return 1.0f;
} }
const auto anisotropic_settings = Settings::values.max_anisotropy.GetValue(); const auto anisotropic_settings = Settings::values.max_anisotropy.GetValue();

View file

@ -345,6 +345,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
const bool is_qualcomm = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY; const bool is_qualcomm = driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY;
const bool is_turnip = driver_id == VK_DRIVER_ID_MESA_TURNIP; const bool is_turnip = driver_id == VK_DRIVER_ID_MESA_TURNIP;
const bool is_s8gen2 = device_id == 0x43050a01; const bool is_s8gen2 = device_id == 0x43050a01;
const bool is_arm = driver_id == VK_DRIVER_ID_ARM_PROPRIETARY;
if ((is_mvk || is_qualcomm || is_turnip) && !is_suitable) { if ((is_mvk || is_qualcomm || is_turnip) && !is_suitable) {
LOG_WARNING(Render_Vulkan, "Unsuitable driver, continuing anyway"); LOG_WARNING(Render_Vulkan, "Unsuitable driver, continuing anyway");
@ -392,7 +393,6 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
CollectPhysicalMemoryInfo(); CollectPhysicalMemoryInfo();
CollectToolingInfo(); CollectToolingInfo();
#ifdef ANDROID
if (is_qualcomm || is_turnip) { if (is_qualcomm || is_turnip) {
LOG_WARNING(Render_Vulkan, LOG_WARNING(Render_Vulkan,
"Qualcomm and Turnip drivers have broken VK_EXT_custom_border_color"); "Qualcomm and Turnip drivers have broken VK_EXT_custom_border_color");
@ -412,7 +412,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
extensions.push_descriptor = false; extensions.push_descriptor = false;
loaded_extensions.erase(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); loaded_extensions.erase(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
#ifdef ARCHITECTURE_arm64 #if defined(ANDROID) && defined(ARCHITECTURE_arm64)
// Patch the driver to enable BCn textures. // Patch the driver to enable BCn textures.
const auto major = (properties.properties.driverVersion >> 24) << 2; const auto major = (properties.properties.driverVersion >> 24) << 2;
const auto minor = (properties.properties.driverVersion >> 12) & 0xFFFU; const auto minor = (properties.properties.driverVersion >> 12) & 0xFFFU;
@ -432,18 +432,23 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
} else { } else {
LOG_WARNING(Render_Vulkan, "Adreno driver can't be patched to enable BCn textures"); LOG_WARNING(Render_Vulkan, "Adreno driver can't be patched to enable BCn textures");
} }
#endif // ARCHITECTURE_arm64 #endif
} }
const bool is_arm = driver_id == VK_DRIVER_ID_ARM_PROPRIETARY;
if (is_arm) { if (is_arm) {
must_emulate_scaled_formats = true; must_emulate_scaled_formats = true;
LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state"); LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state");
extensions.extended_dynamic_state = false; extensions.extended_dynamic_state = false;
loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state2");
features.extended_dynamic_state2.extendedDynamicState2 = false;
features.extended_dynamic_state2.extendedDynamicState2LogicOp = false;
features.extended_dynamic_state2.extendedDynamicState2PatchControlPoints = false;
extensions.extended_dynamic_state2 = false;
loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
} }
#endif // ANDROID
if (is_nvidia) { if (is_nvidia) {
const u32 nv_major_version = (properties.properties.driverVersion >> 22) & 0x3ff; const u32 nv_major_version = (properties.properties.driverVersion >> 22) & 0x3ff;

View file

@ -761,7 +761,7 @@ void Config::ReadRendererValues() {
ReadGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache); ReadGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache);
ReadGlobalSetting(Settings::values.enable_compute_pipelines); ReadGlobalSetting(Settings::values.enable_compute_pipelines);
ReadGlobalSetting(Settings::values.use_video_framerate); ReadGlobalSetting(Settings::values.use_video_framerate);
ReadGlobalSetting(Settings::values.use_aggressive_anisotropic_filtering); ReadGlobalSetting(Settings::values.barrier_feedback_loops);
ReadGlobalSetting(Settings::values.bg_red); ReadGlobalSetting(Settings::values.bg_red);
ReadGlobalSetting(Settings::values.bg_green); ReadGlobalSetting(Settings::values.bg_green);
ReadGlobalSetting(Settings::values.bg_blue); ReadGlobalSetting(Settings::values.bg_blue);
@ -1418,7 +1418,7 @@ void Config::SaveRendererValues() {
WriteGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache); WriteGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache);
WriteGlobalSetting(Settings::values.enable_compute_pipelines); WriteGlobalSetting(Settings::values.enable_compute_pipelines);
WriteGlobalSetting(Settings::values.use_video_framerate); WriteGlobalSetting(Settings::values.use_video_framerate);
WriteGlobalSetting(Settings::values.use_aggressive_anisotropic_filtering); WriteGlobalSetting(Settings::values.barrier_feedback_loops);
WriteGlobalSetting(Settings::values.bg_red); WriteGlobalSetting(Settings::values.bg_red);
WriteGlobalSetting(Settings::values.bg_green); WriteGlobalSetting(Settings::values.bg_green);
WriteGlobalSetting(Settings::values.bg_blue); WriteGlobalSetting(Settings::values.bg_blue);

View file

@ -31,7 +31,6 @@ void ConfigureGraphicsAdvanced::SetConfiguration() {
ui->use_asynchronous_shaders->setEnabled(runtime_lock); ui->use_asynchronous_shaders->setEnabled(runtime_lock);
ui->anisotropic_filtering_combobox->setEnabled(runtime_lock); ui->anisotropic_filtering_combobox->setEnabled(runtime_lock);
ui->enable_compute_pipelines_checkbox->setEnabled(runtime_lock); ui->enable_compute_pipelines_checkbox->setEnabled(runtime_lock);
ui->use_aggressive_anisotropic_filtering->setEnabled(runtime_lock);
ui->async_present->setChecked(Settings::values.async_presentation.GetValue()); ui->async_present->setChecked(Settings::values.async_presentation.GetValue());
ui->renderer_force_max_clock->setChecked(Settings::values.renderer_force_max_clock.GetValue()); ui->renderer_force_max_clock->setChecked(Settings::values.renderer_force_max_clock.GetValue());
@ -44,8 +43,8 @@ void ConfigureGraphicsAdvanced::SetConfiguration() {
ui->enable_compute_pipelines_checkbox->setChecked( ui->enable_compute_pipelines_checkbox->setChecked(
Settings::values.enable_compute_pipelines.GetValue()); Settings::values.enable_compute_pipelines.GetValue());
ui->use_video_framerate_checkbox->setChecked(Settings::values.use_video_framerate.GetValue()); ui->use_video_framerate_checkbox->setChecked(Settings::values.use_video_framerate.GetValue());
ui->use_aggressive_anisotropic_filtering->setChecked( ui->barrier_feedback_loops_checkbox->setChecked(
Settings::values.use_aggressive_anisotropic_filtering.GetValue()); Settings::values.barrier_feedback_loops.GetValue());
if (Settings::IsConfiguringGlobal()) { if (Settings::IsConfiguringGlobal()) {
ui->gpu_accuracy->setCurrentIndex( ui->gpu_accuracy->setCurrentIndex(
@ -97,9 +96,9 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() {
enable_compute_pipelines); enable_compute_pipelines);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_video_framerate, ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_video_framerate,
ui->use_video_framerate_checkbox, use_video_framerate); ui->use_video_framerate_checkbox, use_video_framerate);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_aggressive_anisotropic_filtering, ConfigurationShared::ApplyPerGameSetting(&Settings::values.barrier_feedback_loops,
ui->use_aggressive_anisotropic_filtering, ui->barrier_feedback_loops_checkbox,
use_aggressive_anisotropic_filtering); barrier_feedback_loops);
} }
void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) { void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) {
@ -136,8 +135,8 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
Settings::values.enable_compute_pipelines.UsingGlobal()); Settings::values.enable_compute_pipelines.UsingGlobal());
ui->use_video_framerate_checkbox->setEnabled( ui->use_video_framerate_checkbox->setEnabled(
Settings::values.use_video_framerate.UsingGlobal()); Settings::values.use_video_framerate.UsingGlobal());
ui->use_aggressive_anisotropic_filtering->setEnabled( ui->barrier_feedback_loops_checkbox->setEnabled(
Settings::values.use_aggressive_anisotropic_filtering.UsingGlobal()); Settings::values.barrier_feedback_loops.UsingGlobal());
return; return;
} }
@ -165,9 +164,9 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
ConfigurationShared::SetColoredTristate(ui->use_video_framerate_checkbox, ConfigurationShared::SetColoredTristate(ui->use_video_framerate_checkbox,
Settings::values.use_video_framerate, Settings::values.use_video_framerate,
use_video_framerate); use_video_framerate);
ConfigurationShared::SetColoredTristate(ui->use_aggressive_anisotropic_filtering, ConfigurationShared::SetColoredTristate(ui->barrier_feedback_loops_checkbox,
Settings::values.use_aggressive_anisotropic_filtering, Settings::values.barrier_feedback_loops,
use_aggressive_anisotropic_filtering); barrier_feedback_loops);
ConfigurationShared::SetColoredComboBox( ConfigurationShared::SetColoredComboBox(
ui->gpu_accuracy, ui->label_gpu_accuracy, ui->gpu_accuracy, ui->label_gpu_accuracy,
static_cast<int>(Settings::values.gpu_accuracy.GetValue(true))); static_cast<int>(Settings::values.gpu_accuracy.GetValue(true)));

View file

@ -48,7 +48,7 @@ private:
ConfigurationShared::CheckState use_vulkan_driver_pipeline_cache; ConfigurationShared::CheckState use_vulkan_driver_pipeline_cache;
ConfigurationShared::CheckState enable_compute_pipelines; ConfigurationShared::CheckState enable_compute_pipelines;
ConfigurationShared::CheckState use_video_framerate; ConfigurationShared::CheckState use_video_framerate;
ConfigurationShared::CheckState use_aggressive_anisotropic_filtering; ConfigurationShared::CheckState barrier_feedback_loops;
const Core::System& system; const Core::System& system;
}; };

View file

@ -201,6 +201,16 @@ Compute pipelines are always enabled on all other drivers.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="barrier_feedback_loops_checkbox">
<property name="toolTip">
<string>Improves rendering of transparency effects in specific games.</string>
</property>
<property name="text">
<string>Barrier feedback loops</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QWidget" name="af_layout" native="true"> <widget class="QWidget" name="af_layout" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_1"> <layout class="QHBoxLayout" name="horizontalLayout_1">
@ -260,19 +270,6 @@ Compute pipelines are always enabled on all other drivers.</string>
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="use_aggressive_anisotropic_filtering">
<property name="toolTip">
<string>Enable this option for a more aggressive approach to applying Anisotropic Filtering to textures.
By toggling this, Anisotropic Filtering is added to textures with both nearest and linear mipmapping modes.
This may result in improved visual quality for a wider range of textures, but can also introduce artifacts in
some titles.</string>
</property>
<property name="text">
<string>Apply Anisotropic Filtering for all mipmap modes</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View file

@ -321,7 +321,6 @@ void Config::ReadValues() {
ReadSetting("Renderer", Settings::values.astc_recompression); ReadSetting("Renderer", Settings::values.astc_recompression);
ReadSetting("Renderer", Settings::values.use_fast_gpu_time); ReadSetting("Renderer", Settings::values.use_fast_gpu_time);
ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache); ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache);
ReadSetting("Renderer", Settings::values.use_aggressive_anisotropic_filtering);
ReadSetting("Renderer", Settings::values.bg_red); ReadSetting("Renderer", Settings::values.bg_red);
ReadSetting("Renderer", Settings::values.bg_green); ReadSetting("Renderer", Settings::values.bg_green);

View file

@ -325,10 +325,6 @@ aspect_ratio =
# 0: Default, 1: 2x, 2: 4x, 3: 8x, 4: 16x # 0: Default, 1: 2x, 2: 4x, 3: 8x, 4: 16x
max_anisotropy = max_anisotropy =
# Apply Anisotropic Filtering to all mipmap modes.
# 0 (default): Off, 1: On
use_aggressive_anisotropic_filtering =
# Whether to enable VSync or not. # Whether to enable VSync or not.
# OpenGL: Values other than 0 enable VSync # OpenGL: Values other than 0 enable VSync
# Vulkan: FIFO is selected if the requested mode is not supported by the driver. # Vulkan: FIFO is selected if the requested mode is not supported by the driver.