[TEST] Adjustments over the vkformat undefined and border color swizzle

This commit is contained in:
CamilleLaVey
2026-08-16 19:59:23 -04:00
parent 20a775ed08
commit f6668ef01b
5 changed files with 137 additions and 34 deletions
@@ -370,7 +370,7 @@ inline void PushImageDescriptors(TextureCache& texture_cache,
const VkImageView null_image_view{texture_cache.GetImageView(VideoCommon::NULL_IMAGE_VIEW_ID).Handle(desc.type)};
if (null_image_view != VK_NULL_HANDLE) vk_image_view = null_image_view;
}
const Sampler& sampler{texture_cache.GetSampler(sampler_id)};
Sampler& sampler{texture_cache.GetSampler(sampler_id)};
const bool use_fallback_sampler{sampler.HasAddedAnisotropy() &&
!image_view.SupportsAnisotropy()};
VkSampler vk_sampler{use_fallback_sampler ? sampler.HandleWithDefaultAnisotropy()
@@ -383,8 +383,11 @@ inline void PushImageDescriptors(TextureCache& texture_cache,
!image_view.SupportsDepthComparison()) {
vk_sampler = sampler.HandleWithoutDepthComparison();
}
if (sampler.HasSrgbBorderColor() &&
VideoCore::Surface::IsPixelFormatSRGB(image_view.format)) {
const bool srgb_border{sampler.HasSrgbBorderColor() &&
VideoCore::Surface::IsPixelFormatSRGB(image_view.format)};
if (sampler.NeedsSwizzleMapping() && !image_view.HasIdentitySwizzle()) {
vk_sampler = sampler.HandleWithSwizzle(image_view.Swizzle(), srgb_border);
} else if (srgb_border) {
vk_sampler = sampler.HandleWithSrgbBorderColor();
}
if (sampler.HasMinmaxReduction() && !image_view.SupportsMinmaxFilter()) {
@@ -2405,6 +2405,14 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT) != 0;
}
requires_border_color_format = NeedsExplicitBorderColorFormat(format_info.format);
swizzle_mapping = VkComponentMapping{
.r = ComponentSwizzle(swizzle[0]),
.g = ComponentSwizzle(swizzle[1]),
.b = ComponentSwizzle(swizzle[2]),
.a = ComponentSwizzle(swizzle[3]),
};
has_identity_swizzle = swizzle[0] == SwizzleSource::R && swizzle[1] == SwizzleSource::G &&
swizzle[2] == SwizzleSource::B && swizzle[3] == SwizzleSource::A;
const VkImageUsageFlags requested_view_usage = ImageUsageFlags(format_info, format);
const VkImageUsageFlags image_usage = image.UsageFlags();
const VkImageUsageFlags clamped_view_usage = requested_view_usage & image_usage;
@@ -2429,12 +2437,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
.image = image.Handle(),
.viewType = VkImageViewType{},
.format = format_info.format,
.components{
.r = ComponentSwizzle(swizzle[0]),
.g = ComponentSwizzle(swizzle[1]),
.b = ComponentSwizzle(swizzle[2]),
.a = ComponentSwizzle(swizzle[3]),
},
.components = swizzle_mapping,
.subresourceRange = MakeSubresourceRange(aspect_mask, info.range),
};
const auto create = [&](TextureType tex_type, std::optional<u32> num_layers) {
@@ -2671,6 +2674,33 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& t
min_filter == VK_FILTER_LINEAR ||
mipmap_mode == VK_SAMPLER_MIPMAP_MODE_LINEAR};
const auto make_create_info = [&](const f32 anisotropy, bool force_nearest,
bool disable_compare, const void* chain,
VkBorderColor fixed_border) {
return VkSamplerCreateInfo{
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
.pNext = chain,
.flags = 0,
.magFilter = force_nearest ? VK_FILTER_NEAREST : mag_filter,
.minFilter = force_nearest ? VK_FILTER_NEAREST : min_filter,
.mipmapMode = force_nearest ? VK_SAMPLER_MIPMAP_MODE_NEAREST : mipmap_mode,
.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>(!force_nearest && anisotropy > 1.0f ? VK_TRUE : VK_FALSE),
.maxAnisotropy = force_nearest ? 1.0f : anisotropy,
.compareEnable = disable_compare ? VK_FALSE
: static_cast<VkBool32>(tsc.depth_compare_enabled),
.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 = fixed_border,
.unnormalizedCoordinates = VK_FALSE,
};
};
const auto create_sampler = [&](const f32 anisotropy, bool force_nearest,
bool disable_compare = false,
bool disable_custom_border = false,
@@ -2698,28 +2728,8 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& t
fixed_border = ConvertBorderColor(srgb_color);
}
}
return device.GetLogical().CreateSampler(VkSamplerCreateInfo{
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
.pNext = chain,
.flags = 0,
.magFilter = force_nearest ? VK_FILTER_NEAREST : mag_filter,
.minFilter = force_nearest ? VK_FILTER_NEAREST : min_filter,
.mipmapMode = force_nearest ? VK_SAMPLER_MIPMAP_MODE_NEAREST : mipmap_mode,
.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>(!force_nearest && anisotropy > 1.0f ? VK_TRUE : VK_FALSE),
.maxAnisotropy = force_nearest ? 1.0f : anisotropy,
.compareEnable = disable_compare ? VK_FALSE
: static_cast<VkBool32>(tsc.depth_compare_enabled),
.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 = fixed_border,
.unnormalizedCoordinates = VK_FALSE,
});
return device.GetLogical().CreateSampler(
make_create_info(anisotropy, force_nearest, disable_compare, chain, fixed_border));
};
sampler = create_sampler(max_anisotropy, false);
@@ -2744,6 +2754,60 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& t
sampler_srgb_border =
create_sampler(max_anisotropy, false, false, false, false, true);
}
needs_swizzle_mapping = has_custom_border_colors && device.NeedsBorderColorSwizzleMapping();
if (needs_swizzle_mapping) {
device_ptr = &device;
border_color_value = color;
srgb_border_color_value = srgb_color;
swizzle_reduction_mode = reduction_ci.reductionMode;
swizzle_uses_reduction = has_minmax_reduction;
swizzle_base_ci = make_create_info(max_anisotropy, false, false, nullptr,
VK_BORDER_COLOR_FLOAT_CUSTOM_EXT);
}
}
VkSampler Sampler::HandleWithSwizzle(const VkComponentMapping& mapping, bool srgb) {
const auto matches = [&](const SwizzleVariant& variant) {
return variant.srgb == srgb && variant.mapping.r == mapping.r &&
variant.mapping.g == mapping.g && variant.mapping.b == mapping.b &&
variant.mapping.a == mapping.a;
};
const auto it = std::ranges::find_if(swizzle_variants, matches);
if (it != swizzle_variants.end()) {
return *it->sampler;
}
std::array<float, 4> value = border_color_value;
if (srgb) {
value = srgb_border_color_value;
}
const VkSamplerCustomBorderColorCreateInfoEXT border_ci{
.sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT,
.pNext = nullptr,
.customBorderColor = std::bit_cast<VkClearColorValue>(value),
.format = VK_FORMAT_UNDEFINED,
};
const VkSamplerBorderColorComponentMappingCreateInfoEXT mapping_ci{
.sType = VK_STRUCTURE_TYPE_SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT,
.pNext = &border_ci,
.components = mapping,
.srgb = VK_FALSE,
};
const VkSamplerReductionModeCreateInfoEXT reduction_ci{
.sType = VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT,
.pNext = &mapping_ci,
.reductionMode = swizzle_reduction_mode,
};
VkSamplerCreateInfo create_info = swizzle_base_ci;
create_info.pNext = &mapping_ci;
if (swizzle_uses_reduction) {
create_info.pNext = &reduction_ci;
}
swizzle_variants.push_back(SwizzleVariant{
.mapping = mapping,
.srgb = srgb,
.sampler = device_ptr->GetLogical().CreateSampler(create_info),
});
return *swizzle_variants.back().sampler;
}
Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM_RT> color_buffers,
@@ -422,6 +422,14 @@ public:
return supports_minmax_filter;
}
[[nodiscard]] const VkComponentMapping& Swizzle() const noexcept {
return swizzle_mapping;
}
[[nodiscard]] bool HasIdentitySwizzle() const noexcept {
return has_identity_swizzle;
}
[[nodiscard]] GPUVAddr GpuAddr() const noexcept {
return gpu_addr;
}
@@ -454,9 +462,12 @@ private:
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
u32 buffer_size = 0;
VkComponentMapping swizzle_mapping{};
bool supports_depth_comparison = false;
bool requires_border_color_format = false;
bool supports_minmax_filter = false;
bool has_identity_swizzle = true;
};
class ImageAlloc : public VideoCommon::ImageAllocBase {};
@@ -517,7 +528,19 @@ public:
return static_cast<bool>(sampler_srgb_border);
}
[[nodiscard]] bool NeedsSwizzleMapping() const noexcept {
return needs_swizzle_mapping;
}
[[nodiscard]] VkSampler HandleWithSwizzle(const VkComponentMapping& mapping, bool srgb);
private:
struct SwizzleVariant {
VkComponentMapping mapping;
bool srgb;
vk::Sampler sampler;
};
vk::Sampler sampler;
vk::Sampler sampler_default_anisotropy;
vk::Sampler sampler_nearest;
@@ -525,6 +548,15 @@ private:
vk::Sampler sampler_default_border;
vk::Sampler sampler_default_reduction;
vk::Sampler sampler_srgb_border;
std::vector<SwizzleVariant> swizzle_variants;
const Device* device_ptr = nullptr;
VkSamplerCreateInfo swizzle_base_ci{};
VkSamplerReductionModeEXT swizzle_reduction_mode = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT;
std::array<float, 4> border_color_value{};
std::array<float, 4> srgb_border_color_value{};
bool swizzle_uses_reduction = false;
bool needs_swizzle_mapping = false;
};
struct TextureCacheParams {
@@ -1343,9 +1343,7 @@ void Device::RemoveUnsuitableExtensions() {
// VK_EXT_border_color_swizzle
if (extensions.border_color_swizzle) {
extensions.border_color_swizzle =
extensions.custom_border_color &&
features.border_color_swizzle.borderColorSwizzle &&
features.border_color_swizzle.borderColorSwizzleFromImage;
extensions.custom_border_color && features.border_color_swizzle.borderColorSwizzle;
}
RemoveExtensionFeatureIfUnsuitable(extensions.border_color_swizzle,
features.border_color_swizzle,
@@ -724,6 +724,12 @@ FN_MAX_LIMIT_LIST
return extensions.border_color_swizzle;
}
/// Returns true if samplers must be carried with border color swizzle mapping.
bool NeedsBorderColorSwizzleMapping() const {
return extensions.border_color_swizzle &&
!features.border_color_swizzle.borderColorSwizzleFromImage;
}
/// Returns true if borderColorSwizzleFromImage is available.
bool IsBorderColorSwizzleFromImageSupported() const {
return features.border_color_swizzle.borderColorSwizzleFromImage;