Vulkan: Fix bug with fractional LOD bias and min/max LOD
This commit is contained in:
parent
5e29508b8f
commit
f595fe080f
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue