diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 8aa292b1..891b2608 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -233,6 +233,7 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) { ctx.AddExecutionMode(main, spv::ExecutionMode::OriginUpperLeft); } if (info.has_discard) { + ctx.AddExtension("SPV_EXT_demote_to_helper_invocation"); ctx.AddCapability(spv::Capability::DemoteToHelperInvocationEXT); } if (info.stores.Get(IR::Attribute::Depth)) { diff --git a/src/video_core/buffer_cache/buffer.cpp b/src/video_core/buffer_cache/buffer.cpp index f8afd699..5a049c18 100644 --- a/src/video_core/buffer_cache/buffer.cpp +++ b/src/video_core/buffer_cache/buffer.cpp @@ -95,7 +95,8 @@ Buffer::Buffer(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_, // Create buffer object. const vk::BufferCreateInfo buffer_ci = { .size = size_bytes, - .usage = flags, + // When maintenance5 is not supported, use all flags since we can't add flags to views. + .usage = instance->IsMaintenance5Supported() ? flags : AllFlags, }; VmaAllocationInfo alloc_info{}; buffer.Create(buffer_ci, usage, &alloc_info); @@ -119,7 +120,7 @@ vk::BufferView Buffer::View(u32 offset, u32 size, bool is_written, AmdGpu::DataF : vk::BufferUsageFlagBits2KHR::eUniformTexelBuffer, }; const vk::BufferViewCreateInfo view_ci = { - .pNext = &usage_flags, + .pNext = instance->IsMaintenance5Supported() ? &usage_flags : nullptr, .buffer = buffer.buffer, .format = Vulkan::LiverpoolToVK::SurfaceFormat(dfmt, nfmt), .offset = offset, diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index ce79d423..c10cac6c 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -88,11 +88,17 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul "Rectangle List primitive type is only supported for embedded VS"); } + auto prim_restart = key.enable_primitive_restart != 0; + if (prim_restart && IsPrimitiveListTopology() && !instance.IsListRestartSupported()) { + LOG_WARNING(Render_Vulkan, + "Primitive restart is enabled for list topology but not supported by driver."); + prim_restart = false; + } const vk::PipelineInputAssemblyStateCreateInfo input_assembly = { .topology = LiverpoolToVK::PrimitiveType(key.prim_type), - .primitiveRestartEnable = key.enable_primitive_restart != 0, + .primitiveRestartEnable = prim_restart, }; - ASSERT_MSG(!key.enable_primitive_restart || key.primitive_restart_index == 0xFFFF || + ASSERT_MSG(!prim_restart || key.primitive_restart_index == 0xFFFF || key.primitive_restart_index == 0xFFFFFFFF, "Primitive restart index other than -1 is not supported yet"); @@ -387,7 +393,7 @@ void GraphicsPipeline::BindResources(const Liverpool::Regs& regs, for (const auto& buffer : stage->buffers) { const auto vsharp = buffer.GetSharp(*stage); const bool is_storage = buffer.IsStorage(vsharp); - if (vsharp) { + if (vsharp && vsharp.GetSize() > 0) { const VAddr address = vsharp.base_address; if (texture_cache.IsMeta(address)) { LOG_WARNING(Render_Vulkan, "Unexpected metadata read by a PS shader (buffer)"); diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index dda9183a..753e2f94 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -84,6 +84,16 @@ public: return key.depth_stencil.depth_enable.Value(); } + [[nodiscard]] bool IsPrimitiveListTopology() const { + return key.prim_type == Liverpool::PrimitiveType::PointList || + key.prim_type == Liverpool::PrimitiveType::LineList || + key.prim_type == Liverpool::PrimitiveType::TriangleList || + key.prim_type == Liverpool::PrimitiveType::AdjLineList || + key.prim_type == Liverpool::PrimitiveType::AdjTriangleList || + key.prim_type == Liverpool::PrimitiveType::RectList || + key.prim_type == Liverpool::PrimitiveType::QuadList; + } + private: void BuildDescSetLayout(); diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 2aeb77ec..022ef16c 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -260,9 +260,8 @@ bool Instance::CreateDevice() { color_write_en &= add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME); const bool calibrated_timestamps = add_extension(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME); const bool robustness = add_extension(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME); - const bool topology_restart = - add_extension(VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME); - const bool maintenance5 = add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); + list_restart = add_extension(VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME); + maintenance5 = add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); // These extensions are promoted by Vulkan 1.3, but for greater compatibility we use Vulkan 1.2 // with extensions. @@ -415,7 +414,7 @@ bool Instance::CreateDevice() { if (!workgroup_memory_explicit_layout) { device_chain.unlink(); } - if (!topology_restart) { + if (!list_restart) { device_chain.unlink(); } if (robustness) { diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index e6e39ab1..e019ffba 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -138,6 +138,15 @@ public: return null_descriptor; } + /// Returns true when VK_KHR_maintenance5 is supported. + bool IsMaintenance5Supported() const { + return maintenance5; + } + + bool IsListRestartSupported() const { + return list_restart; + } + /// Returns the vendor ID of the physical device u32 GetVendorID() const { return properties.vendorID; @@ -280,6 +289,8 @@ private: bool color_write_en{}; bool vertex_input_dynamic_state{}; bool null_descriptor{}; + bool maintenance5{}; + bool list_restart{}; u64 min_imported_host_pointer_alignment{}; u32 subgroup_size{}; bool tooling_info{};