[vk] Even more validation fixes that require extensive testing
Some checks failed
eden-license / license-header (pull_request) Failing after 28s

This commit is contained in:
Ribbit 2025-09-27 12:39:28 -07:00
parent 2d97d0f108
commit 334856d585
8 changed files with 116 additions and 17 deletions

View file

@ -1432,6 +1432,9 @@ void EmitContext::DefineInputs(const IR::Program& program) {
}
if (info.uses_sample_id) {
sample_id = DefineInput(*this, U32[1], false, spv::BuiltIn::SampleId);
if (stage == Stage::Fragment) {
Decorate(sample_id, spv::Decoration::Flat);
}
}
if (info.uses_is_helper_invocation) {
is_helper_invocation = DefineInput(*this, U1, false, spv::BuiltIn::HelperInvocation);
@ -1442,6 +1445,13 @@ void EmitContext::DefineInputs(const IR::Program& program) {
subgroup_mask_le = DefineInput(*this, U32[4], false, spv::BuiltIn::SubgroupLeMaskKHR);
subgroup_mask_gt = DefineInput(*this, U32[4], false, spv::BuiltIn::SubgroupGtMaskKHR);
subgroup_mask_ge = DefineInput(*this, U32[4], false, spv::BuiltIn::SubgroupGeMaskKHR);
if (stage == Stage::Fragment) {
Decorate(subgroup_mask_eq, spv::Decoration::Flat);
Decorate(subgroup_mask_lt, spv::Decoration::Flat);
Decorate(subgroup_mask_le, spv::Decoration::Flat);
Decorate(subgroup_mask_gt, spv::Decoration::Flat);
Decorate(subgroup_mask_ge, spv::Decoration::Flat);
}
}
if (info.uses_fswzadd || info.uses_subgroup_invocation_id || info.uses_subgroup_shuffles ||
(profile.warp_size_potentially_larger_than_guest &&
@ -1461,6 +1471,9 @@ void EmitContext::DefineInputs(const IR::Program& program) {
}
if (loads[IR::Attribute::PrimitiveId]) {
primitive_id = DefineInput(*this, U32[1], false, spv::BuiltIn::PrimitiveId);
if (stage == Stage::Fragment) {
Decorate(primitive_id, spv::Decoration::Flat);
}
}
if (loads[IR::Attribute::Layer]) {
AddCapability(spv::Capability::Geometry);

View file

@ -5,11 +5,11 @@
#extension GL_ARB_shader_stencil_export : require
layout(binding = 0) uniform sampler2D depth_tex;
layout(binding = 1) uniform isampler2D stencil_tex;
layout(binding = 1) uniform usampler2D stencil_tex;
layout(location = 0) in vec2 texcoord;
void main() {
gl_FragDepth = textureLod(depth_tex, texcoord, 0).r;
gl_FragStencilRefARB = textureLod(stencil_tex, texcoord, 0).r;
gl_FragStencilRefARB = int(textureLod(stencil_tex, texcoord, 0).r);
}

View file

@ -193,8 +193,8 @@ inline void PushImageDescriptors(TextureCache& texture_cache,
const Sampler& sampler{texture_cache.GetSampler(sampler_id)};
const bool use_fallback_sampler{sampler.HasAddedAnisotropy() &&
!image_view.SupportsAnisotropy()};
const bool enable_compare =
sampler.DepthCompareEnabled() && image_view.SupportsDepthCompare();
const bool enable_compare = sampler.DepthCompareEnabled() &&
image_view.SupportsDepthCompare(desc.type);
const VkSampler vk_sampler =
sampler.HandleForUsage(use_fallback_sampler, enable_compare);
guest_descriptor_queue.AddSampledImage(vk_image_view, vk_sampler);

View file

@ -306,14 +306,48 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities) {
swapchain_ci.queueFamilyIndexCount = static_cast<u32>(queue_indices.size());
swapchain_ci.pQueueFamilyIndices = queue_indices.data();
}
static constexpr std::array view_formats{VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_B8G8R8A8_SRGB};
const VkFormat swapchain_format = surface_format.format;
const bool has_mutable_swapchain = device.IsKhrSwapchainMutableFormatEnabled();
#ifdef ANDROID
// Android is already ordered the same as Switch.
VkFormat preferred_view_format = VK_FORMAT_R8G8B8A8_UNORM;
#else
VkFormat preferred_view_format = VK_FORMAT_B8G8R8A8_UNORM;
#endif
if (!has_mutable_swapchain) {
preferred_view_format = swapchain_format;
}
std::array<VkFormat, 4> view_formats{};
u32 view_format_count = 0;
const auto push_format = [&](VkFormat format) {
if (format == VK_FORMAT_UNDEFINED || view_format_count >= static_cast<u32>(view_formats.size())) {
return;
}
const auto end_iterator = view_formats.begin() + view_format_count;
if (std::find(view_formats.begin(), end_iterator, format) != end_iterator) {
return;
}
view_formats[view_format_count++] = format;
};
push_format(swapchain_format);
if (has_mutable_swapchain) {
push_format(preferred_view_format);
if (swapchain_format == VK_FORMAT_B8G8R8A8_UNORM ||
preferred_view_format == VK_FORMAT_B8G8R8A8_UNORM) {
push_format(VK_FORMAT_B8G8R8A8_SRGB);
}
if (swapchain_format == VK_FORMAT_R8G8B8A8_UNORM ||
preferred_view_format == VK_FORMAT_R8G8B8A8_UNORM) {
push_format(VK_FORMAT_R8G8B8A8_SRGB);
}
}
VkImageFormatListCreateInfo format_list{
.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR,
.pNext = nullptr,
.viewFormatCount = static_cast<u32>(view_formats.size()),
.viewFormatCount = view_format_count,
.pViewFormats = view_formats.data(),
};
if (device.IsKhrSwapchainMutableFormatEnabled()) {
if (has_mutable_swapchain && view_format_count > 1) {
format_list.pNext = std::exchange(swapchain_ci.pNext, &format_list);
swapchain_ci.flags |= VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR;
}
@ -331,12 +365,7 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities) {
images = swapchain.GetImages();
image_count = static_cast<u32>(images.size());
#ifdef ANDROID
// Android is already ordered the same as Switch.
image_view_format = VK_FORMAT_R8G8B8A8_UNORM;
#else
image_view_format = VK_FORMAT_B8G8R8A8_UNORM;
#endif
image_view_format = preferred_view_format;
}
void Swapchain::CreateSemaphores() {

View file

@ -2010,6 +2010,8 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
samples(ConvertSampleCount(image.info.num_samples)) {
using Shader::TextureType;
sampled_formats.fill(VK_FORMAT_UNDEFINED);
const VkImageAspectFlags aspect_mask = ImageViewAspectMask(info);
std::array<SwizzleSource, 4> swizzle{
SwizzleSource::R,
@ -2026,6 +2028,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
}
}
const auto format_info = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, format);
view_format = format_info.format;
VkImageUsageFlags view_usage = ImageUsageFlags(format_info, format);
const VkImageUsageFlags image_usage = image.UsageFlags();
const VkImageUsageFlags original_view_usage = view_usage;
@ -2074,6 +2077,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
handle.SetObjectNameEXT(VideoCommon::Name(*this, gpu_addr).c_str());
}
image_views[static_cast<size_t>(tex_type)] = std::move(handle);
sampled_formats[static_cast<size_t>(tex_type)] = ci.format;
};
switch (info.type) {
case VideoCommon::ImageViewType::e1D:
@ -2113,10 +2117,14 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageInfo& info,
const VideoCommon::ImageViewInfo& view_info, GPUVAddr gpu_addr_)
: VideoCommon::ImageViewBase{info, view_info, gpu_addr_},
buffer_size{VideoCommon::CalculateGuestSizeInBytes(info)} {}
buffer_size{VideoCommon::CalculateGuestSizeInBytes(info)} {
sampled_formats.fill(VK_FORMAT_UNDEFINED);
view_format = VK_FORMAT_UNDEFINED;
}
ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageViewParams& params)
: VideoCommon::ImageViewBase{params}, device{&runtime.device} {
sampled_formats.fill(VK_FORMAT_UNDEFINED);
if (device->HasNullDescriptor()) {
return;
}
@ -2129,7 +2137,9 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::NullImageV
image_handle = *null_image;
for (u32 i = 0; i < Shader::NUM_TEXTURE_TYPES; i++) {
image_views[i] = MakeView(VK_FORMAT_A8B8G8R8_UNORM_PACK32, VK_IMAGE_ASPECT_COLOR_BIT);
sampled_formats[i] = VK_FORMAT_A8B8G8R8_UNORM_PACK32;
}
view_format = VK_FORMAT_A8B8G8R8_UNORM_PACK32;
}
ImageView::~ImageView() = default;
@ -2200,9 +2210,22 @@ bool ImageView::IsRescaled() const noexcept {
return src_image.IsRescaled();
}
bool ImageView::SupportsDepthCompare() const noexcept {
bool ImageView::SupportsDepthCompare(Shader::TextureType texture_type) const noexcept {
if (device == nullptr || image_handle == VK_NULL_HANDLE) {
return false;
}
const auto surface_type = VideoCore::Surface::GetFormatType(format);
return surface_type == SurfaceType::Depth || surface_type == SurfaceType::DepthStencil;
if (surface_type != SurfaceType::Depth && surface_type != SurfaceType::DepthStencil) {
return false;
}
const VkFormat sampled_format = sampled_formats[static_cast<size_t>(texture_type)];
if (sampled_format != VK_FORMAT_UNDEFINED) {
return device->SupportsDepthComparisonSampling(sampled_format);
}
if (view_format == VK_FORMAT_UNDEFINED) {
return false;
}
return device->SupportsDepthComparisonSampling(view_format);
}
vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask) {

View file

@ -237,7 +237,7 @@ public:
Shader::ImageFormat image_format);
[[nodiscard]] bool IsRescaled() const noexcept;
[[nodiscard]] bool SupportsDepthCompare() const noexcept;
[[nodiscard]] bool SupportsDepthCompare(Shader::TextureType texture_type) const noexcept;
[[nodiscard]] VkImageView Handle(Shader::TextureType texture_type) const noexcept {
return *image_views[static_cast<size_t>(texture_type)];
@ -283,6 +283,8 @@ private:
VkImage image_handle = VK_NULL_HANDLE;
VkImageView render_target = VK_NULL_HANDLE;
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
VkFormat view_format = VK_FORMAT_UNDEFINED;
std::array<VkFormat, Shader::NUM_TEXTURE_TYPES> sampled_formats{};
u32 buffer_size = 0;
};

View file

@ -886,6 +886,34 @@ bool Device::IsFormatSupported(VkFormat wanted_format, VkFormatFeatureFlags want
return (supported_usage & wanted_usage) == wanted_usage;
}
bool Device::SupportsDepthComparisonSampling(VkFormat format) const {
const auto it = format_properties.find(format);
if (it == format_properties.end()) {
UNIMPLEMENTED_MSG("Unimplemented depth comparison query format={}", format);
return false;
}
#if defined(VK_FORMAT_FEATURE_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT)
const auto features = it->second.optimalTilingFeatures;
return (features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT) != 0;
#elif defined(VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT)
const auto get_props2 = reinterpret_cast<PFN_vkGetPhysicalDeviceFormatProperties2>(
dld.vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties2"));
if (!get_props2) {
const auto fallback_features = it->second.optimalTilingFeatures;
return (fallback_features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0;
}
VkFormatProperties3 format_props3{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3};
VkFormatProperties2 format_props2{VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2};
format_props2.pNext = &format_props3;
get_props2(physical, format, &format_props2);
return (format_props3.optimalTilingFeatures &
VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT) != 0;
#else
const auto fallback_features = it->second.optimalTilingFeatures;
return (fallback_features & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0;
#endif
}
std::string Device::GetDriverName() const {
switch (properties.driver.driverID) {
case VK_DRIVER_ID_AMD_PROPRIETARY:
@ -1448,3 +1476,4 @@ std::vector<VkDeviceQueueCreateInfo> Device::GetDeviceQueueCreateInfos() const {
}
} // namespace Vulkan

View file

@ -213,6 +213,9 @@ public:
bool IsFormatSupported(VkFormat wanted_format, VkFormatFeatureFlags wanted_usage,
FormatType format_type) const;
/// Returns true when the format supports depth comparison sampling on optimal tiling images.
bool SupportsDepthComparisonSampling(VkFormat format) const;
/// Reports a device loss.
void ReportLoss() const;