Vulkan: Fix bug with fractional LOD bias and min/max LOD

This commit is contained in:
Stenzek 2016-10-02 23:53:09 +10:00
parent 5e29508b8f
commit f595fe080f
4 changed files with 22 additions and 29 deletions

View File

@ -130,8 +130,8 @@ union SamplerState {
BitField<5, 2, VkSamplerAddressMode> wrap_v; BitField<5, 2, VkSamplerAddressMode> wrap_v;
BitField<7, 8, u32> min_lod; BitField<7, 8, u32> min_lod;
BitField<15, 8, u32> max_lod; BitField<15, 8, u32> max_lod;
BitField<23, 6, s32> lod_bias; // tm0.lod_bias (8 bits) / 32 gives us 0-7. BitField<23, 8, s32> lod_bias;
BitField<29, 3, u32> anisotropy; // max_anisotropy = 1 << anisotropy, max of 16, so range 0-4. BitField<31, 1, u32> enable_anisotropic_filtering;
u32 bits; u32 bits;
}; };

View File

@ -784,11 +784,6 @@ VkSampler ObjectCache::GetSampler(const SamplerState& info)
if (iter != m_sampler_cache.end()) if (iter != m_sampler_cache.end())
return iter->second; 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 = { VkSamplerCreateInfo create_info = {
VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType
nullptr, // const void* pNext nullptr, // const void* pNext
@ -799,17 +794,26 @@ VkSampler ObjectCache::GetSampler(const SamplerState& info)
info.wrap_u, // VkSamplerAddressMode addressModeU info.wrap_u, // VkSamplerAddressMode addressModeU
info.wrap_v, // VkSamplerAddressMode addressModeV info.wrap_v, // VkSamplerAddressMode addressModeV
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW
static_cast<float>(info.lod_bias.Value()), // float mipLodBias static_cast<float>(info.lod_bias / 32.0f), // float mipLodBias
anisotropy_enable, // VkBool32 anisotropyEnable VK_FALSE, // VkBool32 anisotropyEnable
max_anisotropy, // float maxAnisotropy 0.0f, // float maxAnisotropy
VK_FALSE, // VkBool32 compareEnable VK_FALSE, // VkBool32 compareEnable
VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp
static_cast<float>(info.min_lod.Value()), // float minLod static_cast<float>(info.min_lod / 16.0f), // float minLod
static_cast<float>(info.max_lod.Value()), // float maxLod static_cast<float>(info.max_lod / 16.0f), // float maxLod
VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor
VK_FALSE // VkBool32 unnormalizedCoordinates 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; VkSampler sampler = VK_NULL_HANDLE;
VkResult res = vkCreateSampler(g_vulkan_context->GetDevice(), &create_info, nullptr, &sampler); VkResult res = vkCreateSampler(g_vulkan_context->GetDevice(), &create_info, nullptr, &sampler);
if (res != VK_SUCCESS) if (res != VK_SUCCESS)

View File

@ -1367,13 +1367,9 @@ void Renderer::SetSamplerState(int stage, int texindex, bool custom_tex)
} }
// If mipmaps are disabled, clamp min/max lod // If mipmaps are disabled, clamp min/max lod
new_state.max_lod = (SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0)) ? new_state.max_lod = SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0) ? tm1.max_lod : 0;
static_cast<u32>(MathUtil::Clamp(tm1.max_lod / 16.0f, 0.0f, 255.0f)) : new_state.min_lod = std::min(new_state.max_lod.Value(), tm1.min_lod);
0; new_state.lod_bias = SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0) ? tm0.lod_bias : 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);
// Custom textures may have a greater number of mips // Custom textures may have a greater number of mips
if (custom_tex) 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]; new_state.wrap_v = address_modes[tm0.wrap_t];
// Only use anisotropic filtering for textures that would be linearly filtered. // Only use anisotropic filtering for textures that would be linearly filtered.
if (g_vulkan_context->SupportsAnisotropicFiltering() && g_ActiveConfig.iMaxAnisotropy > 0 && new_state.enable_anisotropic_filtering = SamplerCommon::IsBpTexMode0PointFiltering(tm0) ? 0 : 1;
!SamplerCommon::IsBpTexMode0PointFiltering(tm0))
{
new_state.anisotropy = g_ActiveConfig.iMaxAnisotropy;
}
else
{
new_state.anisotropy = 0;
}
// Skip lookup if the state hasn't changed. // Skip lookup if the state hasn't changed.
size_t bind_index = (texindex * 4) + stage; size_t bind_index = (texindex * 4) + stage;
@ -1417,6 +1405,7 @@ void Renderer::SetSamplerState(int stage, int texindex, bool custom_tex)
void Renderer::ResetSamplerStates() void Renderer::ResetSamplerStates()
{ {
// Ensure none of the sampler objects are in use. // 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(); g_command_buffer_mgr->WaitForGPUIdle();
// Invalidate all sampler states, next draw will re-initialize them. // Invalidate all sampler states, next draw will re-initialize them.

View File

@ -93,7 +93,7 @@ public:
{ {
return m_device_properties.limits.bufferImageGranularity; 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 // Finds a memory type index for the specified memory properties and the bits returned by
// vkGetImageMemoryRequirements // vkGetImageMemoryRequirements
bool GetMemoryType(u32 bits, VkMemoryPropertyFlags properties, u32* out_type_index); bool GetMemoryType(u32 bits, VkMemoryPropertyFlags properties, u32* out_type_index);