|
|
|
@ -2209,6 +2209,7 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& t |
|
|
|
const auto& device = runtime.device; |
|
|
|
const bool arbitrary_borders = runtime.device.IsExtCustomBorderColorSupported(); |
|
|
|
const auto color = tsc.BorderColor(); |
|
|
|
compare_enabled = tsc.depth_compare_enabled != 0; |
|
|
|
|
|
|
|
const VkSamplerCustomBorderColorCreateInfoEXT border_ci{ |
|
|
|
.sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT, |
|
|
|
@ -2234,21 +2235,28 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& t |
|
|
|
// Some games have samplers with garbage. Sanitize them here.
|
|
|
|
const f32 max_anisotropy = std::clamp(tsc.MaxAnisotropy(), 1.0f, 16.0f); |
|
|
|
|
|
|
|
const auto create_sampler = [&](const f32 anisotropy) { |
|
|
|
const VkFilter orig_mag = MaxwellToVK::Sampler::Filter(tsc.mag_filter); |
|
|
|
const VkFilter orig_min = MaxwellToVK::Sampler::Filter(tsc.min_filter); |
|
|
|
const VkSamplerMipmapMode orig_mipmap = MaxwellToVK::Sampler::MipmapMode(tsc.mipmap_filter); |
|
|
|
|
|
|
|
has_linear_filtering = (orig_mag == VK_FILTER_LINEAR) || (orig_min == VK_FILTER_LINEAR) || |
|
|
|
(orig_mipmap == VK_SAMPLER_MIPMAP_MODE_LINEAR); |
|
|
|
|
|
|
|
const auto create_sampler = [&](const f32 anisotropy, VkBool32 compare_enable) { |
|
|
|
return device.GetLogical().CreateSampler(VkSamplerCreateInfo{ |
|
|
|
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, |
|
|
|
.pNext = pnext, |
|
|
|
.flags = 0, |
|
|
|
.magFilter = MaxwellToVK::Sampler::Filter(tsc.mag_filter), |
|
|
|
.minFilter = MaxwellToVK::Sampler::Filter(tsc.min_filter), |
|
|
|
.mipmapMode = MaxwellToVK::Sampler::MipmapMode(tsc.mipmap_filter), |
|
|
|
.magFilter = orig_mag, |
|
|
|
.minFilter = orig_min, |
|
|
|
.mipmapMode = orig_mipmap, |
|
|
|
.addressModeU = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_u, 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), |
|
|
|
.mipLodBias = tsc.LodBias(), |
|
|
|
.anisotropyEnable = static_cast<VkBool32>(anisotropy > 1.0f ? VK_TRUE : VK_FALSE), |
|
|
|
.maxAnisotropy = anisotropy, |
|
|
|
.compareEnable = tsc.depth_compare_enabled, |
|
|
|
.compareEnable = compare_enable, |
|
|
|
.compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func), |
|
|
|
.minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.MinLod(), |
|
|
|
.maxLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.25f : tsc.MaxLod(), |
|
|
|
@ -2258,11 +2266,59 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& t |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
sampler = create_sampler(max_anisotropy); |
|
|
|
const auto create_sampler_force_nearest = [&](const f32 anisotropy, VkBool32 compare_enable) { |
|
|
|
return device.GetLogical().CreateSampler(VkSamplerCreateInfo{ |
|
|
|
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, |
|
|
|
.pNext = pnext, |
|
|
|
.flags = 0, |
|
|
|
.magFilter = VK_FILTER_NEAREST, |
|
|
|
.minFilter = VK_FILTER_NEAREST, |
|
|
|
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST, |
|
|
|
.addressModeU = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_u, 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), |
|
|
|
.mipLodBias = tsc.LodBias(), |
|
|
|
.anisotropyEnable = static_cast<VkBool32>(anisotropy > 1.0f ? VK_TRUE : VK_FALSE), |
|
|
|
.maxAnisotropy = anisotropy, |
|
|
|
.compareEnable = compare_enable, |
|
|
|
.compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func), |
|
|
|
.minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.MinLod(), |
|
|
|
.maxLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.25f : tsc.MaxLod(), |
|
|
|
.borderColor = |
|
|
|
arbitrary_borders ? VK_BORDER_COLOR_FLOAT_CUSTOM_EXT : ConvertBorderColor(color), |
|
|
|
.unnormalizedCoordinates = VK_FALSE, |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
const VkBool32 compare_flag = compare_enabled ? VK_TRUE : VK_FALSE; |
|
|
|
sampler = create_sampler(max_anisotropy, compare_flag); |
|
|
|
if (compare_enabled) { |
|
|
|
sampler_no_compare = create_sampler(max_anisotropy, VK_FALSE); |
|
|
|
} |
|
|
|
|
|
|
|
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); |
|
|
|
sampler_default_anisotropy = create_sampler(max_anisotropy_default, compare_flag); |
|
|
|
if (compare_enabled) { |
|
|
|
sampler_default_anisotropy_no_compare = |
|
|
|
create_sampler(max_anisotropy_default, VK_FALSE); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// If any linear filtering was requested, create forced-nearest variants for integer formats.
|
|
|
|
if (has_linear_filtering) { |
|
|
|
sampler_nearest = create_sampler_force_nearest(max_anisotropy, compare_flag); |
|
|
|
if (compare_enabled) { |
|
|
|
sampler_nearest_no_compare = create_sampler_force_nearest(max_anisotropy, VK_FALSE); |
|
|
|
} |
|
|
|
if (max_anisotropy > max_anisotropy_default) { |
|
|
|
sampler_nearest_default_anisotropy = |
|
|
|
create_sampler_force_nearest(max_anisotropy_default, compare_flag); |
|
|
|
if (compare_enabled) { |
|
|
|
sampler_nearest_default_anisotropy_no_compare = |
|
|
|
create_sampler_force_nearest(max_anisotropy_default, VK_FALSE); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|