video_core: Fix a few validation errors (#4555)

* shader_recompiler: Don't add SignedZeroInfNanPreserve if not supported

* renderer_vulkan: Respect patch list restart support flag
This commit is contained in:
squidbus 2026-06-12 16:30:59 -07:00 committed by GitHub
parent f8c38ba782
commit 8c4e3926bb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 41 additions and 12 deletions

View File

@ -559,9 +559,21 @@ void SetupRoundingMode(EmitContext& ctx, const Profile& profile, const RuntimeIn
void SetupInfNanPreserveMode(EmitContext& ctx, const Profile& profile,
const RuntimeInfo& runtime_info, Id main_func) {
ctx.AddCapability(spv::Capability::SignedZeroInfNanPreserve);
// universally supported (98.85% on gpuinfo) so no flag checked
ctx.AddExecutionMode(main_func, spv::ExecutionMode::SignedZeroInfNanPreserve, 32U);
if (profile.support_fp16_signed_zero_inf_nan_preserve ||
profile.support_fp32_signed_zero_inf_nan_preserve ||
profile.support_fp64_signed_zero_inf_nan_preserve) {
ctx.AddCapability(spv::Capability::SignedZeroInfNanPreserve);
}
if (profile.support_fp32_signed_zero_inf_nan_preserve) {
ctx.AddExecutionMode(main_func, spv::ExecutionMode::SignedZeroInfNanPreserve, 32U);
} else {
static std::once_flag logged;
std::call_once(logged, [] {
LOG_WARNING(Render_Vulkan,
"Float32 signed zero/inf/nan preserve mode is not supported by the GPU");
});
}
if (ctx.info.uses_fp16) {
if (profile.support_fp16_signed_zero_inf_nan_preserve) {
ctx.AddExecutionMode(main_func, spv::ExecutionMode::SignedZeroInfNanPreserve, 16U);

View File

@ -280,6 +280,14 @@ bool Instance::CreateDevice() {
depth_clip_enable = add_extension(VK_EXT_DEPTH_CLIP_ENABLE_EXTENSION_NAME);
vertex_input_dynamic_state = add_extension(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
list_restart = add_extension(VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME);
if (list_restart) {
list_restart_features =
feature_chain.get<vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT>();
LOG_INFO(Render_Vulkan, "- primitiveTopologyListRestart: {}",
list_restart_features.primitiveTopologyListRestart);
LOG_INFO(Render_Vulkan, "- primitiveTopologyPatchListRestart: {}",
list_restart_features.primitiveTopologyPatchListRestart);
}
amd_shader_explicit_vertex_parameter =
add_extension(VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME);
if (!amd_shader_explicit_vertex_parameter) {
@ -369,8 +377,6 @@ bool Instance::CreateDevice() {
.pQueuePriorities = queue_priorities.data(),
};
const auto topology_list_restart_features =
feature_chain.get<vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT>();
const auto vk11_features = feature_chain.get<vk::PhysicalDeviceVulkan11Features>();
vk12_features = feature_chain.get<vk::PhysicalDeviceVulkan12Features>();
vk13_features = feature_chain.get<vk::PhysicalDeviceVulkan13Features>();
@ -464,9 +470,9 @@ bool Instance::CreateDevice() {
.vertexInputDynamicState = true,
},
vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT{
.primitiveTopologyListRestart = true,
.primitiveTopologyListRestart = list_restart_features.primitiveTopologyListRestart,
.primitiveTopologyPatchListRestart =
topology_list_restart_features.primitiveTopologyPatchListRestart,
list_restart_features.primitiveTopologyPatchListRestart,
},
vk::PhysicalDeviceFragmentShaderBarycentricFeaturesKHR{
.fragmentShaderBarycentric = true,

View File

@ -180,9 +180,14 @@ public:
return amd_shader_explicit_vertex_parameter;
}
/// Returns true when VK_EXT_primitive_topology_list_restart is supported.
/// Returns true when VK_EXT_primitive_topology_list_restart is supported for regular lists.
bool IsListRestartSupported() const {
return list_restart;
return list_restart && list_restart_features.primitiveTopologyListRestart;
}
/// Returns true when VK_EXT_primitive_topology_list_restart is supported for patch lists.
bool IsPatchListRestartSupported() const {
return list_restart && list_restart_features.primitiveTopologyPatchListRestart;
}
/// Returns true when VK_EXT_legacy_vertex_attributes is supported.
@ -485,6 +490,7 @@ private:
vk::PhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR
workgroup_memory_explicit_layout_features;
vk::PhysicalDeviceImage2DViewOf3DFeaturesEXT image_2d_view_of_3d_features;
vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT list_restart_features;
vk::DriverIdKHR driver_id;
vk::UniqueDebugUtilsMessengerEXT debug_callback{};
std::string vendor_name;

View File

@ -1295,13 +1295,18 @@ void Rasterizer::UpdatePrimitiveState(const bool is_indexed) const {
topology == vk::PrimitiveTopology::eLineList ||
topology == vk::PrimitiveTopology::eTriangleList ||
topology == vk::PrimitiveTopology::eLineListWithAdjacency ||
topology == vk::PrimitiveTopology::eTriangleListWithAdjacency ||
topology == vk::PrimitiveTopology::ePatchList;
topology == vk::PrimitiveTopology::eTriangleListWithAdjacency;
};
const auto is_patch_list_topology = [](const AmdGpu::PrimitiveType type) {
// Quad and rect lists are emulated using tessellation.
return type == AmdGpu::PrimitiveType::PatchPrimitive ||
type == AmdGpu::PrimitiveType::QuadList || type == AmdGpu::PrimitiveType::RectList;
};
const auto prim_restart =
(regs.enable_primitive_restart & 1) != 0 &&
(instance.IsListRestartSupported() || !is_list_topology(regs.primitive_type));
(instance.IsListRestartSupported() || !is_list_topology(regs.primitive_type)) &&
(instance.IsPatchListRestartSupported() || !is_patch_list_topology(regs.primitive_type));
ASSERT_MSG(!is_indexed || !prim_restart || regs.primitive_restart_index == 0xFFFF ||
regs.primitive_restart_index == 0xFFFFFFFF,
"Primitive restart index other than -1 is not supported yet");