diff --git a/Source/Core/VideoBackends/Vulkan/Constants.h b/Source/Core/VideoBackends/Vulkan/Constants.h index d6ac8d7ae2..a135c76180 100644 --- a/Source/Core/VideoBackends/Vulkan/Constants.h +++ b/Source/Core/VideoBackends/Vulkan/Constants.h @@ -130,8 +130,8 @@ union SamplerState { BitField<5, 2, VkSamplerAddressMode> wrap_v; BitField<7, 8, u32> min_lod; BitField<15, 8, u32> max_lod; - BitField<23, 6, s32> lod_bias; // tm0.lod_bias (8 bits) / 32 gives us 0-7. - BitField<29, 3, u32> anisotropy; // max_anisotropy = 1 << anisotropy, max of 16, so range 0-4. + BitField<23, 8, s32> lod_bias; + BitField<31, 1, u32> enable_anisotropic_filtering; u32 bits; }; diff --git a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp index 6932830bfb..cf90fc2f60 100644 --- a/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp +++ b/Source/Core/VideoBackends/Vulkan/ObjectCache.cpp @@ -784,11 +784,6 @@ VkSampler ObjectCache::GetSampler(const SamplerState& info) if (iter != m_sampler_cache.end()) return iter->second; - // Cap anisotropy to device limits. - VkBool32 anisotropy_enable = (info.anisotropy != 0) ? VK_TRUE : VK_FALSE; - float max_anisotropy = std::min(static_cast(1 << info.anisotropy), - g_vulkan_context->GetMaxSaxmplerAnisotropy()); - VkSamplerCreateInfo create_info = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType nullptr, // const void* pNext @@ -799,17 +794,26 @@ VkSampler ObjectCache::GetSampler(const SamplerState& info) info.wrap_u, // VkSamplerAddressMode addressModeU info.wrap_v, // VkSamplerAddressMode addressModeV VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW - static_cast(info.lod_bias.Value()), // float mipLodBias - anisotropy_enable, // VkBool32 anisotropyEnable - max_anisotropy, // float maxAnisotropy + static_cast(info.lod_bias / 32.0f), // float mipLodBias + VK_FALSE, // VkBool32 anisotropyEnable + 0.0f, // float maxAnisotropy VK_FALSE, // VkBool32 compareEnable VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp - static_cast(info.min_lod.Value()), // float minLod - static_cast(info.max_lod.Value()), // float maxLod + static_cast(info.min_lod / 16.0f), // float minLod + static_cast(info.max_lod / 16.0f), // float maxLod VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor VK_FALSE // VkBool32 unnormalizedCoordinates }; + // Can we use anisotropic filtering with this sampler? + if (info.enable_anisotropic_filtering && g_vulkan_context->SupportsAnisotropicFiltering()) + { + // Cap anisotropy to device limits. + create_info.anisotropyEnable = VK_TRUE; + create_info.maxAnisotropy = std::min(static_cast(1 << g_ActiveConfig.iMaxAnisotropy), + g_vulkan_context->GetMaxSamplerAnisotropy()); + } + VkSampler sampler = VK_NULL_HANDLE; VkResult res = vkCreateSampler(g_vulkan_context->GetDevice(), &create_info, nullptr, &sampler); if (res != VK_SUCCESS) diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index 4a0c29bac3..7bb15aacdf 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -1367,13 +1367,9 @@ void Renderer::SetSamplerState(int stage, int texindex, bool custom_tex) } // If mipmaps are disabled, clamp min/max lod - new_state.max_lod = (SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0)) ? - static_cast(MathUtil::Clamp(tm1.max_lod / 16.0f, 0.0f, 255.0f)) : - 0; - new_state.min_lod = - std::min(new_state.max_lod.Value(), - static_cast(MathUtil::Clamp(tm1.min_lod / 16.0f, 0.0f, 255.0f))); - new_state.lod_bias = static_cast(tm0.lod_bias / 32.0f); + new_state.max_lod = SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0) ? tm1.max_lod : 0; + new_state.min_lod = std::min(new_state.max_lod.Value(), tm1.min_lod); + new_state.lod_bias = SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0) ? tm0.lod_bias : 0; // Custom textures may have a greater number of mips if (custom_tex) @@ -1387,15 +1383,7 @@ void Renderer::SetSamplerState(int stage, int texindex, bool custom_tex) new_state.wrap_v = address_modes[tm0.wrap_t]; // Only use anisotropic filtering for textures that would be linearly filtered. - if (g_vulkan_context->SupportsAnisotropicFiltering() && g_ActiveConfig.iMaxAnisotropy > 0 && - !SamplerCommon::IsBpTexMode0PointFiltering(tm0)) - { - new_state.anisotropy = g_ActiveConfig.iMaxAnisotropy; - } - else - { - new_state.anisotropy = 0; - } + new_state.enable_anisotropic_filtering = SamplerCommon::IsBpTexMode0PointFiltering(tm0) ? 0 : 1; // Skip lookup if the state hasn't changed. size_t bind_index = (texindex * 4) + stage; @@ -1417,6 +1405,7 @@ void Renderer::SetSamplerState(int stage, int texindex, bool custom_tex) void Renderer::ResetSamplerStates() { // Ensure none of the sampler objects are in use. + // This assumes that none of the samplers are in use on the command list currently being recorded. g_command_buffer_mgr->WaitForGPUIdle(); // Invalidate all sampler states, next draw will re-initialize them. diff --git a/Source/Core/VideoBackends/Vulkan/VulkanContext.h b/Source/Core/VideoBackends/Vulkan/VulkanContext.h index 382163b654..8227f1e6af 100644 --- a/Source/Core/VideoBackends/Vulkan/VulkanContext.h +++ b/Source/Core/VideoBackends/Vulkan/VulkanContext.h @@ -93,7 +93,7 @@ public: { return m_device_properties.limits.bufferImageGranularity; } - float GetMaxSaxmplerAnisotropy() const { return m_device_properties.limits.maxSamplerAnisotropy; } + float GetMaxSamplerAnisotropy() const { return m_device_properties.limits.maxSamplerAnisotropy; } // Finds a memory type index for the specified memory properties and the bits returned by // vkGetImageMemoryRequirements bool GetMemoryType(u32 bits, VkMemoryPropertyFlags properties, u32* out_type_index);