Skip to content

Commit

Permalink
Vulkan: Fix bug with fractional LOD bias and min/max LOD
Browse files Browse the repository at this point in the history
  • Loading branch information
stenzek committed Oct 3, 2016
1 parent 5e29508 commit f595fe0
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 29 deletions.
4 changes: 2 additions & 2 deletions Source/Core/VideoBackends/Vulkan/Constants.h
Expand Up @@ -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;
};
Expand Down
24 changes: 14 additions & 10 deletions Source/Core/VideoBackends/Vulkan/ObjectCache.cpp
Expand Up @@ -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<float>(1 << info.anisotropy),
g_vulkan_context->GetMaxSaxmplerAnisotropy());

VkSamplerCreateInfo create_info = {
VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType
nullptr, // const void* pNext
Expand All @@ -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<float>(info.lod_bias.Value()), // float mipLodBias
anisotropy_enable, // VkBool32 anisotropyEnable
max_anisotropy, // float maxAnisotropy
static_cast<float>(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<float>(info.min_lod.Value()), // float minLod
static_cast<float>(info.max_lod.Value()), // float maxLod
static_cast<float>(info.min_lod / 16.0f), // float minLod
static_cast<float>(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<float>(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)
Expand Down
21 changes: 5 additions & 16 deletions Source/Core/VideoBackends/Vulkan/Renderer.cpp
Expand Up @@ -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<u32>(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<u32>(MathUtil::Clamp(tm1.min_lod / 16.0f, 0.0f, 255.0f)));
new_state.lod_bias = static_cast<s32>(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)
Expand All @@ -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;
Expand All @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/VideoBackends/Vulkan/VulkanContext.h
Expand Up @@ -93,7 +93,7 @@ class VulkanContext
{
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);
Expand Down

0 comments on commit f595fe0

Please sign in to comment.