From 841ee9fc15d2fc14b48b9f4ccd7cfc3beba8fbe7 Mon Sep 17 00:00:00 2001 From: PixelyIon Date: Tue, 16 Nov 2021 13:53:28 +0530 Subject: [PATCH] Check for `vertexAttributeInstanceRateZeroDivisor` feature before usage Check for `vertexAttributeInstanceRateZeroDivisor` in `VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT` when the Maxwell3D register corresponding to the vertex attribute divisor is set to 0. If it isn't then it logs a warning and sets the value anyway which could result in UB since the only alternative is an exception that stops emulation which might not be optimal if the game mostly works fine without this, we will add a user-facing warning when we intentionally allow UB like this in the future. --- app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h | 4 +++- app/src/main/cpp/skyline/gpu/quirk_manager.cpp | 3 ++- app/src/main/cpp/skyline/gpu/quirk_manager.h | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h index 35185cdb..92d730f8 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h @@ -34,7 +34,7 @@ namespace skyline::gpu::interconnect { u32 high; }; - operator u64&() { + operator u64 &() { return iova; } }; @@ -795,6 +795,8 @@ namespace skyline::gpu::interconnect { void SetVertexBufferDivisor(u32 index, u32 divisor) { if (!gpu.quirks.supportsVertexAttributeDivisor) Logger::Warn("Cannot set vertex attribute divisor without host GPU support"); + else if (divisor == 0 && !gpu.quirks.supportsVertexAttributeZeroDivisor) + Logger::Warn("Cannot set vertex attribute divisor to zero without host GPU support"); vertexBindingDivisors[index].divisor = divisor; } }; diff --git a/app/src/main/cpp/skyline/gpu/quirk_manager.cpp b/app/src/main/cpp/skyline/gpu/quirk_manager.cpp index 0a0d2a49..e9075f47 100644 --- a/app/src/main/cpp/skyline/gpu/quirk_manager.cpp +++ b/app/src/main/cpp/skyline/gpu/quirk_manager.cpp @@ -39,11 +39,12 @@ namespace skyline { } FEAT_SET(vk::PhysicalDeviceFeatures2, features.logicOp, supportsLogicOp) + FEAT_SET(vk::PhysicalDeviceVertexAttributeDivisorFeaturesEXT, vertexAttributeInstanceRateZeroDivisor, supportsVertexAttributeZeroDivisor) #undef FEAT_SET } std::string QuirkManager::Summary() { - return fmt::format("\n* Supports Last Provoking Vertex: {}\n* Supports Logical Operations: {}\n* Supports Vertex Attribute Divisor: {}", supportsLastProvokingVertex, supportsLogicOp, supportsVertexAttributeDivisor); + return fmt::format("\n* Supports Last Provoking Vertex: {}\n* Supports Logical Operations: {}\n* Supports Vertex Attribute Divisor: {}\n* Supports Vertex Attribute Zero Divisor: {}", supportsLastProvokingVertex, supportsLogicOp, supportsVertexAttributeDivisor, supportsVertexAttributeZeroDivisor); } } diff --git a/app/src/main/cpp/skyline/gpu/quirk_manager.h b/app/src/main/cpp/skyline/gpu/quirk_manager.h index 95029c75..6b85a006 100644 --- a/app/src/main/cpp/skyline/gpu/quirk_manager.h +++ b/app/src/main/cpp/skyline/gpu/quirk_manager.h @@ -15,6 +15,7 @@ namespace skyline { bool supportsLastProvokingVertex{}; //!< If the device supports setting the last vertex as the provoking vertex (with VK_EXT_provoking_vertex) bool supportsLogicOp{}; //!< If the device supports framebuffer logical operations during blending bool supportsVertexAttributeDivisor{}; //!< If the device supports a divisor for instance-rate vertex attributes (with VK_EXT_vertex_attribute_divisor) + bool supportsVertexAttributeZeroDivisor{}; //!< If the device supports a zero divisor for instance-rate vertex attributes (with VK_EXT_vertex_attribute_divisor) QuirkManager() = default;